Untrusted Root - improve Security by Restricting Root

Is it currently being argued towards Untrusted Root?

I.e. do you think it is a good idea to try to restrict malware which gained root access?

examples which may point into that direction:

Goal of untrusted root could be:

  • to protect the virtualizer (and in effect, avoid host compromise, and similarly the hardware to avoid hardware compromise)
  • an untrusted root in Whonix-Workstation might have less options attacking Whonix-Gateway?
  • make kernel compromise non-persistent after reboot through combined use with secure boot?
  • A compromised root is less worse than a compromised kernel? Is that even a valid concept?
  • different goals?
  • other goals?

I don’t know if untrusted root isn’t a fully developed kernel concept yet (or ever).

On untrusted root: UEFI secure boot kernel restrictions [LWN.net]

It is important to make the case of the usefulness or non-usefulness of untrusted root. In case untrusted root is broken by concept, a usability issues, feature breakage may be introduced and time may be wasted on it.

1 Like

To use modprobe, root access is required. If malware already has root access, why bother using modprobe?

If an application runs as root (or any user) under mandatory access control (MAC) such as apparmor or filejail, it cannot use modprobe since MAC would prevent that.

Maybe we have to distinguish between

  • a process running as root and MAC,
  • “full root compromise”, i.e. a process that runs unconfined (without MAC) as root
  • and kernel compromise?

The question of this thread is, is the kernel capable to resist full root compromise?

2 Likes

Because root and kernel is not the same. As said, there are more ways to compromise the kernel. Afaik loading a module is the most common/easiest way. Even if it wasn’t, why give the attacker more opportunities.

Which is a big if. Whonix does not do that by default, and, same as above, even if it would, why give the attacker more opportunities?

2 Likes

I see this having some advantage. Kernel privileges are greater than traditional root.

This is one of the reasons why setting kernel.modules_disabled=1 with sysctl would be a good idea.

Edit by Patrick: enforce kernel module software signature verification [module signing] / disallow kernel module loading by default

1 Like

One way to do this would be to do something with Linux capabilities.

libpam-cap allows you to give users specific capabilities with /etc/security/capability.conf but this doesn’t seem to work with the root account.

We can drop all privileges as the root user by running capsh --drop=all -- but it’d be tricky to somehow set this by default. We could add that to the bashrc and make it immutable but that doesn’t seem like a good way to do this due to it depending on the root user sourcing that file.

SELinux can also restrict individual users but it will be way too complicated to maintain.

1 Like

I don’t know yet if this is a good idea or will break a ton of things. Please test.

However, I hereby contribute to the brainstorming on how this could be implemented technically.

Upstream bug report?

Yes and root can make non-immutable or login with a different shell or something else. Therefore other ideas…

Random ideas…

  1. Run during boot using systemd? OR

  1. pam_exec? Examples:

1 Like

I don’t think this is a bug. The pam developers probably never intended for root to be restricted with this.

Only if we give root the CAP_SYS_IMMUTABLE capability which would be disallowed.

We can restrict the amount of valid shells in /etc/shells and add the same command to each of their rcs.

capsh only applies for the current session. Running it during boot would just apply the changes to that specific service.

I’m not sure that would work as pam_exec doesn’t run commands as specific users AFAIK

1 Like

Did run pam_exec without seteuid option just now. Result:
whoami returns user.
I.e. pam_exec can run programs as the user which is attempting to login.
Makes sense. pam is there to set up a (user interactive or non-interactive) session. It can run programs before the user can interfere. Might be possible to run capsh.

(With seteuid option used it runs it as root.)

2 Likes

https://www.linuxjournal.com/magazine/making-root-unprivileged

1 Like

Untrusted Root makes sense with my current understanding. Reasons:

Quote linux - Methods root can use to elevate itself to kernel mode - Information Security Stack Exchange

When most Linux users hear “root”, they think of the maximum possible privilege on a computer. Some even think that root runs in ring 0. But in reality, root is just a regular user running in ring 3, albeit one which the kernel trusts (many sensitive kernel operations are guarded with checks along the lines of if (!uid_eq(current_uid(), GLOBAL_ROOT_UID)) return -EPERM; to prevent abuse, which simply returns an error if uid != 0 ).

It would be good if we could trap a compromised root account in user space and prevent a compromised root from getting kernel mode access.

This would be useful to protect the virtualizer or perhaps even the hardware.

Quote Linux kernel developer Kees Cook kexec: add sysctl to disable kexec_load [LWN.net] (8 Jan 2014)

The intention is for using this in environments where “perfect” enforcement is hard. Without a verified boot, along with verified modules, and along with verified kexec, this is trying to give a system a better chance to defend itself (or at least grow the window of discoverability) against attack in the face of a privilege escalation.

In my mind, I consider several boot scenarios:

  1. Verified boot of read-only verified root fs loading fd-based verification of kexec images.
  2. Secure boot of writable root fs loading signed kexec images.
  3. Regular boot loading kexec (e.g. kcrash) image early and locking it.
  4. Regular boot with no control of kexec image at all.

Since that is an old quote, things might have improved by now.

At first sight untrusted root looks pointless since root has write access to maliciously alter the bootloader, kernel image, initial ramdisk (initrd) or any other file on the disk. Therefore at least after reboot, a compromised root could escalate to compromised kernel mode. But this is not always the case:

  • In Qubes TemplateBasedVMs the root image (where the bootloader, kernel and initrd and more resides) is writeable but non-persistent after reboot. In other words, a malicious modification for example of the kernel image would be gone after reboot of the TemplateBasedVM.
  • Using this verified boot idea the same could be accomplished outside of Qubes TemplateBasedVMs. I.e. the same could be accomplished with Debian. A read-only boot medium using debcheckroot (and more to verify initrd, bootloader and whatnot) could make sure that kernel, bootloader, initrd and all non-auto/non-user files shipped by any packages are verified.

And malware re-starting itself from the user’s home folder might be restricted too.

Vulnerable files such as ~/.bashrc or folders such as ~/.config/autostart could be checked and/or restored to known sane versions at early boot time when it is considered that no malware is running yet.

The question is, can we disable all the “easy” (non-kernel exploit) ways to prevent root from getting access to kernel space?

That is before reboot - because root can change bootloader, kernel image, etc. and after reboot changes to bootloader, kernel image, etc. must be undone. That might include enforce kernel module software signature verification [module signing] / disallow kernel module loading by default, disable kexec which we are already doing, and whatnot.

A good starting point might be:

Perhaps it may even be possible to prevent root from modifying the bootloader, kernel image, initrd? Perhaps it could be configured that such changes must happen through use of apt-get? But then additional, malicious /etc/apt/sources.list.d/ sources.list or apt command line parameters to set malicious sources.list might be set. Some restrictions (if even possible) might have to go into separate, opt-in packages or opt-in commands if functionality gets restricted too much (such as packages.debian.org as sources only).

2 Likes

There isn’t really a plausible way to prevent root from modifying it but you can make sure it isn’t executed if it’s modified. For example, see Android’s verified boot implementation. I’m not sure how this could be implemented in an ordinary Linux distro.

1 Like

I am very interested in verified boot latetly. For VMs:
Could be implemented using similar to this idea in this very post: enable Linux kernel gpg verification in grub and/or enable Secure Boot by default - #15 by Patrick
In essence initially boot from a readonly boot medium, do verification and chainload (kexec) (boot) regular disk if verification was ok.

Also described a bit in Are non-perfect Defenses that defeat off-the-shelf Viruses a worthwhile Development Goal?

For host: not sure yet. Perhaps using Secure Boot. Perhaps similar to above. Should be possible though because…

SilverBlue and ClearLinux do interesting things related to it. They call it stateless.

This blog describes it very well.

Once stateless, verified boot gets a lot simpler.

2 Likes

What is root needed for for the average Whonix user?
I can only come up with few stuff like apt-get + some other listed here: https://www.whonix.org/wiki/Common_Whonix_CLI_Commands
Are there any commonly used programs which need root at runtime?

1 Like

Without root/sudo goes long way.

(Maybe search wiki for sudo and grep Whonix source code for sudo.)

Why you’re asking?

Can we somehow disable or even delete the root user? If possible this might make sense in a nonpersistent + noroot boot.

From there we can expand.

Yes, thats the idea I had in mind.
When grepping through the source code most stuff was related to apt, also sdwdate + some whonix scripts. I don’t know if you can restrict sudo to a limited set of commands. Also apparmor could maybe restrict the few remaining cases and forbid everything else for root. In case the system would use something like dm-verity apt-get would also be pointless I guess. You would need some other mechanism to push upgrades.

1 Like

These special cases and upgrading aren’t blockers. Solutions can be searched later. It’s worth pursuing this idea of disabling/deleting independently. For example for boot in live + noroot it totally makes sense.

1 Like

I’d imagine many systemd services would be running as the root user.

I don’t think this would be the best idea. As I said above, many services would be running as the root user and deleting root entirely would break it unless systemd can somehow grant more privileges as it’s the init process.

Running sudo userdel -f root kinda worked but the root user was back again after a reboot.

Any we care about at live boot?

Yes. Nearly every service runs as the root user. Running

grep "User=" /lib/systemd/system/*.service

just shows a few services. If a service doesn’t select a specific user, it uses the root user by default.

1 Like

Ahh sure. Let me rephrase it: Is there any reason an average user would need to elevate its privileges to run program X?

1 Like