security-misc icon indicating copy to clipboard operation
security-misc copied to clipboard

why remount-secure even needed? fix insecure mount options at the root, not here

Open adrelanos opened this issue 9 months ago • 74 comments

Which software / source code sets the initial insecure mount options anyhow?

Could we fix it there instead of adding a band-aid on top?

adrelanos avatar Nov 05 '23 19:11 adrelanos

Well, actually there is a better way. A solution that is no band-aid. And it is modifiying the fstab. There is also another solution, that is direct and involves no remounting. We can write custom systemd mount targets and ship them with the package. The only problem with the latter is, fstab entries take precedence over those units. So we can't harden what is covered in fstab with this way.

monsieuremre avatar Nov 05 '23 19:11 monsieuremre

Like if the user has a seperate /home volume, we can't harden it with our custom systemd unit. I think the reason behind this is, systemd dynamically overrides our unit with the unit it auto generates from fstab on startup.

monsieuremre avatar Nov 05 '23 19:11 monsieuremre

That doesn't really answer why it's insecure by Debian (or most Linux distributions) default.

adrelanos avatar Nov 05 '23 20:11 adrelanos

Because by default debian and most distributions don't do too much disk partitioning. If you want a seperate tmp or var partition, most of the time you manually configure them when installing. And bind mounting to itself is clever workaround to get all the good mounting option benefits without having the partition itself, but it is really not that surprising that no distro would mount a directory to itself by default.

monsieuremre avatar Nov 05 '23 20:11 monsieuremre

A very highly unrelated sidenote: the only distribution that I see who ships secure defaults by default is openSUSE. Debian by default ships with very slack file permissions for anything. OpenSUSE however ships with already mostly hardened defaults. Tumbleweed gets a score of 87 on lynis after a default install. Debian and most other distros get like 60. And this isn't surprising, because Debian does not try to be better desktop or server os. Debian tries to be the universal os, compatible with every device ever. So actually makes sense for them to ship slack defaults. A price to pay for universal compatibility.

monsieuremre avatar Nov 05 '23 20:11 monsieuremre

Where is the source code where it says "use these default mount options for this and that partition"?

adrelanos avatar Nov 05 '23 22:11 adrelanos

Like if the user has a seperate /home volume, we can't harden it with our custom systemd unit. I think the reason behind this is, systemd dynamically overrides our unit with the unit it auto generates from fstab on startup.

Created https://github.com/Kicksecure/security-misc/issues/161 for it.

adrelanos avatar Nov 06 '23 00:11 adrelanos

quote https://lists.freedesktop.org/archives/systemd-devel/2019-December/043845.html

On a standard Debian system, the three tmpfs mounts (/run, /tmp, /dev/shm) already have the nosuid and nodev options – this is hardcoded in mount-setup.c. So you should first figure out why they are not present in your case to begin with.

This might be the referenced source file: https://github.com/hramrach/systemd-1/blob/master/src/core/mount-setup.c

a) The remount-secure.service unit file should run alone. Non-parallel. Until remount-secure.service is done, no other systemd unit files should be run. Is that possible with systemd?

Have it run before systemd (i.e. do it from the initramfs). If I remember correctly, if the initramfs pre-mounts /run &c. with the correct options, then systemd will just use that as-is and won't downgrade to the hardcoded options.

This implies that initramfs (initramfs-tools, dracut) is responsible for mount options too.

adrelanos avatar Nov 06 '23 00:11 adrelanos

Ok I tell you the source. Systemd calls the binart mount with the option --all on boot. And mount, unless the mount options are overriden with the option --option or -o, looks for the options in the fstab file, which by default has the path /etc/fstab. What we can do is:

  • We modify the mount package. Uninstall the one packaged by debian, package our own, modify the source, make the fstab path default to /something/kicksecure/fstab, and the world is good.
  • Modify the calling of mount --all, and make it be called with mount --all --fstab /something/kicksecure/fstab.
  • Don't play any games and just override the fstab, for simplicity.

These would not be necessary for stuff that have no entries in fstab. Like if the use has no seperate partition for var, we can create a var.mount systemd unit and define our default options there and life would be easy. But unfortunately, if there is a var entry in fstab, our unit will be overridden.

monsieuremre avatar Nov 07 '23 13:11 monsieuremre

But dracut earlier also already uses mount? Or do you mean the systemd which already runs during dracut?

I couldn't find yet the mount options that dracut uses.

adrelanos avatar Nov 07 '23 18:11 adrelanos

When you mount, if you do -o or --options, then you define options, overriding what was the default. If you don't override, then mount looks into fstab for the options. When no options there, then it looks to the respective systemd unit. If it doesn't exist too, then it gives out an error. This is my understanding.

monsieuremre avatar Nov 07 '23 20:11 monsieuremre

At least 3 different things we could accomplish here.

  • A) Harden mount options of newly built Kicksecure (or Whonix) VM images. And/or,
  • B) Harden mount options of newly built Kicksecure (or Whonix) ISO images. And/or,
  • C) Harden mount options of arbitrary systems (such as a Debian based server which gets distribution morphed into Kicksecure).

In case of A),

  • for non-Qubes Kicksecure based, the question is why isn't /etc/fstab hardened by default. It's because it's built by grml-debootstrap's (in Debian) chroot-script.
    • We could contribute to grml-debootstrap to harden /etc/fstab as much as possible as upstream accepts as well as add an option --hardened-fstab or --custom-fstab or something like this with an alternative version that hardens it even more (such as in case upstream does not want to mount /home with noexec by default).
  • in case of Qubes, their /etc/fstab is here and I've recently sent a PR to https://github.com/QubesOS/qubes-core-agent-linux/pull/472 which will maybe be the basis for further improvements.
    • Qubes may or may not accept /home mounted with noexec by default.
    • Related tickets:
      • https://github.com/QubesOS/qubes-issues/issues/5263
      • https://github.com/QubesOS/qubes-issues/issues/5329

In case of B),

  • When installing, it will be probably calamares based. So calamares installer would create /etc/fstab, we'd need to look into how calamares handles that, contribute upstream or write a custom calamares module. But that is blocked until an ISO emerges. (Btw progress was made there recently on ISO building, see deriative-maker help-steps/image-to-iso.)

In case of C),

directly writing to /etc/fstab from security-misc is risky. Hence such a systemd unit + script makes sense.

adrelanos avatar Nov 08 '23 13:11 adrelanos

dracut also supports /etc/fstab.sys. Not well documented. But can be seen in dracut source code.

adrelanos avatar Nov 08 '23 13:11 adrelanos

Yeah I don't think that will work. Pushing to debian upstream. Like it might, but the debian team is very unresponsive unless it is a bug fix. It would happen probably, but like, in about 3 debian releases later. We can just make our own good defaults ISO. Which isn't that hard to be honest. I feel like we are on our own for the most part tho.

I don't want to take every opportunity to shill suse, so I'm sorry. But opensuse puts in effort to harden their default fstab entries.

monsieuremre avatar Nov 08 '23 14:11 monsieuremre

Pushing to debian upstream. Like it might, but the debian team is very unresponsive unless it is a bug fix. It would happen probably, but like, in about 3 debian releases later.

Debian isn't a conglomerate. It depends on the individual packages, maintainers. I was talking about grml-debootstrap. Pushing fixes to grml-debootstrap seems entirely doable. I managed to land a few patches in grml-debootstrap. The only condition is that it needs to be clean, high quality code. You can see my commits here: https://github.com/grml/grml-debootstrap/commits/master

It doesn't take long either until it reaches derivative-maker. I copied grml-debootstrap to derivative-maker source code folder. A soft fork if you want so. (Not with the intention splitting from upstream due to disagreement or running a separate project. Just to make the updated code available earlier in derivative-maker waiting for the next major Debian release. No big story.)

grml-debootstrap recently learned arm64 support which was contributed by a Whonix contributor. Upstream grml-debootstrap took even did the cleanup / refactoring commits. Building VM images with EFI and Secure Boot was also recently contributed and merged by another contributor.

Until now, grml-debootstrap upstream is entirely reasonable. I might even be capable of running a "full fork" of grml-debootstrap should upstream disappear which I don't hope because they've been doing great work for years.

Improving grml-debootstrap fstab will result in improved Kicksecure VM images. (Would also be possible to leave grml-debootstrap as is and add a better fstab at the derivative-maker level only but that would be more hacky and less beneficial for the overall ecosystem, less use and testing, less bugs only happening inside Kicksecure and derivatives.)

Non-responsiveness of other Debian maintainers is inapplicable here.

adrelanos avatar Nov 08 '23 20:11 adrelanos

Debian isn't a conglomerate. It depends on the individual packages, maintainers.

You are right. I was talking about changes you would suggest debian to make in their iso installer. In that case they would not be involved anyway.

And also the unresponsiveness of debian maintainers are not meant in a bad way. They are very responsive on security fixes and bug fixes, but thats pretty much it. If they wanted, they could be responsive to feature requests, if they weren't shipping one billion packages in their repositories, which even for them is really impossible to maintain. Instead they choose the way of trying to be the universal os. Which I think is something that holds kicksecure back. There are two things I see that are holding kicksecure back. First is QubesOS compatibility. Which is understandable and there isn't much to do against this. The second is debian. Debian's package freezing is really not we want. Like even if you fix your thing upstream, good luck waiting another 2 years till the next debian, in which that version still might not be in the repos anyway. And they even microcode updates too, between point releases. This is also, a no no for a security system. Actually imma open an issue in a sec with a suggestion.

monsieuremre avatar Nov 09 '23 12:11 monsieuremre

Debian isn't a conglomerate. It depends on the individual packages, maintainers.

You are right. I was talking about changes you would suggest debian to make in their iso installer. In that case they would not be involved anyway.

Btw the installer would be calamares based which is also a project independent of Debian which apparently is popular, used by many Linux distributions nowadays, configurable, supports plugins, is responsive. It's also packaged for Debian.

Any fstab issues could be reported there. However, I am not sure how great the chances are of fstab hardening feature requests to be implemented without also sending a pull request doing the actual implementation. Testing calamares fstab and feature request if applicable would be a helpful contribution nonetheless to see what upstream calamares thinks about this.

(A calamare based installer is entirely realistic. There once was a Whonix-Host installer. Implying that the same would be possible for Kicksecure. The calamares config files can nowadays be found in Kicksecure package live-config-dist. It was deprecated for other reasons because it was based on isolinux bootloader, only supported legacy BIOS booting, EFI booting was unsupported with no known solution on how to fix that. The new upcoming implementation won't have these issues.)

adrelanos avatar Nov 09 '23 18:11 adrelanos

A completely different approach would be having no fstab at all. I've had a chat with chatgpt on this topic: https://chat.openai.com/share/0c573e00-06bf-41a1-8f86-010624172bdc

In summary, use bootloader, dracut and systemd mounts to mount the root disk and everything else.

Not sure that is possible with grub. systemd-boot might be capable of that. But systemd-boot isn't signed by Debian yet. [1] For rather mysterious reasons if you read that ticket. [2]

Dunno if the Boot Loader Specification (BLS) is required which grub might not support. I couldn't find a ticket for grub. Seems like some distributions as Fedora are patching grub.

In summary, seems difficult to research and create a stable implementation to me.

[1] https://groups.google.com/g/linux.debian.bugs.dist/c/n0-eRL6eVtQ https://salsa.debian.org/systemd-team/systemd/-/merge_requests/132 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=996202

adrelanos avatar Nov 09 '23 18:11 adrelanos

In summary, seems difficult to research and create a stable implementation to me.

Well then I am really pleased to share that I have found a way. Real, no bandaid, no workaround. Just mounting stuff the way we want it. I tested it too. It's just writing mount units, but they have to be under etc.

From the manpage:

If a mount point is configured in both /etc/fstab and a unit file that is stored below /usr, the former will take precedence. If the unit file is stored below /etc, it will take precedence. This means: native unit files take precedence over traditional configuration files, but this is superseded by the rule that configuration in /etc will always take precedence over configuration in /usr.

It means exactly what it means. Tho fstab takes precedence over mount units, mount units under etc take precedence even over fstab. So we just create mount unis under etc. We can even do this under a something.mount.d directory to allow the user to override us. The only thing that is problematic is, the mount options. We can not preemptively know before shipping a mount unit for home if needs bind or not. If we tackle that, I think we got a solid solution.

monsieuremre avatar Nov 09 '23 18:11 monsieuremre

How about /usr/lib/systemd/system folder?

adrelanos avatar Nov 09 '23 20:11 adrelanos

Unfortunately doesn't work. Gets overriden by fstab. You can see it in the manpage section I quoted.

monsieuremre avatar Nov 09 '23 20:11 monsieuremre

The only thing that is problematic is, the mount options. We can not preemptively know before shipping a mount unit for home if needs bind or not.

systemd supports many conditionals: https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Conditions%20and%20Asserts

Such as ConditionPathExists, ConditionPathIsSymbolicLink. ConditionPathIsDirectory, ConditionPathIsMountPoint, ConditionDirectoryNotEmpty and many others.

Does that work? If not, please post a systemd feature request. 1) The feature might exist already anyhow 2) they might implement the feature.

adrelanos avatar Nov 09 '23 20:11 adrelanos

I'd still prefer /usr/lib/systemd/system folder.

Then how about /etc/fstab? Well, that's "just a detail". "Just part of the migration plan to this feature."

  • A) For new Kicksecure (VM) builds: They would come without an /etc/fstab, or with an empty /etc/fstab or ideally if possible with an /etc/fstab that only contains comments. (phase 1)
  • B) For existing Kicksecure VM builds that are upgraded: If /etc/fstab is unmodified which it probably is for most users, it might be possible to safely delete it to upgrade users to the new method. This could be done at a later time. (phase 2)
  • C) For distribution morphed installations of Kicksecure such as servers: The migration is more difficult here as somebody or something (an installer) else might have created /etc/fstab. In that case, maybe security-misc should just show a warning during installation and recommend deprecation of /etc/fstab.

These migration details can be tackled later. First priority are the systemd units as a proof of concept.

adrelanos avatar Nov 09 '23 20:11 adrelanos

Yeah, a systemd based implementation would be best. We could deploy the more restrictive mount settings by default. (/home mounted as noexec.) If users want to undo that, they could just use the standard systemd drop-in file mechanism to overrule this. This would be documented in the wiki.

Another detail: For Whonix, tb-starter would need a sudoers exception to run a script which mounts Tor Browser's folder (unfortunately resides in /home) with exec. But that's doable. Got similar code for that already.

adrelanos avatar Nov 09 '23 20:11 adrelanos

Actually we kinda need the fstab to read the mount points. At least initially. Else how would we know where to mount /boot for example? If we write mount units under /usr/lib with --bind options, this might be a good enough solution. If there is no partition, it gets binded to itself with the secure defaults. If there is a partition, it gets overriden by fstab anyway, so the unit will do nothing. This won't harden a the /home directory if it is on a seperate partition for example.

monsieuremre avatar Nov 09 '23 20:11 monsieuremre

Yeah, a systemd based implementation would be best. We could deploy the more restrictive mount settings by default. (/home mounted as noexec.) If users want to undo that, they could just use the standard systemd drop-in file mechanism to overrule this. This would be documented in the wiki.

To avoid user complaints and get everyone on board: https://www.kicksecure.com/wiki/Noexec

adrelanos avatar Nov 09 '23 21:11 adrelanos

Actually we kinda need the fstab to read the mount points. At least initially. Else how would we know where to mount /boot for example?

That is what I meant by

In summary, seems difficult to research and create a stable implementation to me.

in https://github.com/Kicksecure/security-misc/issues/157#issuecomment-1804328208 which also mentions how that might be possible to go completely fstab-less. (grub kernel parameter, dracut to mount the root disk, systemd to handle all other mounts)

It might be the case to go fstab-less would only be possible for (new) Kicksecure (VM) builds where we know the (simple) partitioning. Next version will be built using grml-debootstrap using --vmefi, GPT partition table, separate EFI partition (unfortunately, would prefer without but impossible), no separate /home or /boot partition needed). In that case, even disk UUID is a non-issue thanks to grml-debootstrap FIXED_DISK_IDENTIFIERS=yes build env var.

I had in mind here a completely static systemd mount files configuration. Nothing auto generated by any scripts. Just simple systemd config snippets. And no fstab at all.

This won't harden a the /home directory if it is on a seperate partition for example.

There could be two different systemd mount drop-ins? One with ConditionPathIsDirectory the other with ConditionPathIsMountPoint?

adrelanos avatar Nov 09 '23 21:11 adrelanos

Addressed in the new pull request. For the most part it is solved.

monsieuremre avatar Nov 17 '23 16:11 monsieuremre

Why not "fix it in grml-debootstrap" as mentioned in https://github.com/Kicksecure/security-misc/pull/152#issuecomment-1813544569?

adrelanos avatar Nov 18 '23 03:11 adrelanos

To re-iterate my question.

Why not "fix it in grml-debootstrap" as mentioned in #152 (comment)?


Addressed in the new pull request. For the most part it is solved.

For reference:

  • https://github.com/Kicksecure/security-misc/pull/165

adrelanos avatar Nov 18 '23 03:11 adrelanos