30

Once a *nix system is properly configured and hardened, is it a conceivable strategy to remove all super user/root users? Are there benefits to removing root from a system altogether to prevent super-user privilege escalation exploits altogether?

Edit: More to the point: Can super user (root, uid=0 or otherwise) be replaced entirely with a capability based system?

  • 17
    How would it boot? How would the kernel run? The root user needs to exist for a lot of the underlying operating system to function. – Mike Ounsworth Dec 11 '15 at 18:39
  • 4
    Isn't this the basis of SElinux? "It has no concept of a "root" super-user" en.wikipedia.org/wiki/Security-Enhanced_Linux – KDEx Dec 11 '15 at 19:08
  • 3
    I would love to upvote an Answer to the effect of "SELinux already does this, here's how", if someone with the right knowledge would be kind enough to write one :) – Mike Ounsworth Dec 11 '15 at 19:30
  • 2
    @MikeOunsworth The bootloader and the kernel are not checking, if there is an user with uid 0 in /etc/passwd. – ott-- Dec 11 '15 at 22:12
  • 6
    The Romans lacked a number 0, therefore, they had no root. – gerrit Dec 12 '15 at 10:53
58

Even if you wanted to, I don't think you can remove the root user. From Wikipedia:

On Unix-like systems, for example, the user with a user identifier (UID) of zero is the superuser, regardless of the name of that account.

and a lot of the kernel code that vulnerabilities exploit does stuff like

// become root
uid = 0;
...
if (uid == 0)
    // do some protected thing

So the superuser isn't really a "user account", it's literally the number 0. If you can find an exploit to set uid = 0 then bam! your process has sudo, regardless of whether or not there's a user account named "root".

EDIT ADDRESSING COMMENTS: several flavours of linux prepend a "!" to the root's password in the /etc/shadow password file (a character that can not be generated with the password hashing function) which makes it impossible to actually log in as root. That stops some types of root-priviledge escalation attacks based on cracking the root password, but the more dangerous kind of privilege-escalations are based on buffer-overflow attacks that over-write a process' uid variable to be uid=0, at which point that process is root.

  • 9
    A line of code saying if(uid==0) is completely unaware of passwords or accounts, it's literally checking if an int variable is equal to 0, and letting you do stuff if it is. – Mike Ounsworth Dec 11 '15 at 18:54
  • 7
    Yes, if you can figure out where in memory the uid variable is stored, you can manually set that block of memory to 0, and then your process is running as root (or any other user if you set it to non-zero). Buffer overflows are very good at overwriting memory. – Mike Ounsworth Dec 11 '15 at 18:57
  • 2
    @MikeOunsworth: You make it sound as though the main obstacle attackers face is finding where uid is stored in memory. – Mehrdad Dec 12 '15 at 8:40
  • 4
    @Mehrdad I guess another hard part is finding a buffer overflow to exploit low enough in the kernel code that it's allowed to overwrite the uid variable, which will be in protected kernel memory. But yeah, buffer overflows don't usually give you read access, and if you start overwriting kernel memory blindly, you'll probably just crash the system. – Mike Ounsworth Dec 12 '15 at 13:25
  • 3
    @MikeOunsworth: Yeah, exactly. Even if the address of uid was already fixed to a known value it would barely change the story. The point is that it's in protected memory, not that it's in an unknown location. – Mehrdad Dec 12 '15 at 21:58
27

As argued by others, it makes no sense to "remove" the root UID (which is represented on UNIX as the UID 0). I would go even further and state that it makes no sense to freeze a system into not having any means to provide new privileges. Note that this answer is very opiniated and vague, because the topic to cover is enormous. Let's first go through what being root means on *NIX. I'm going to comment on Linux since it's the most popular *NIX and it comes with specific methods. Hopefully others can cover the BSD families. Let's distinguish what root means in the context of :

  • Discretionary Access Control
  • Linux Security Modules
  • UNIX capabilities
  • User namespaces

Note that in any case, it makes absolutely no sense to blindly apply privilege restrictions system-wide to all binaries that currently run as root. Often these privileges exist for a reason. So you should read the summary below as explaining how you can affect specific services that you run for your unprivileged users and that you want to protect from exploitation.

Discretionary Access Control

Most of permissions for accessing files on *NIX systems are mandated by the DAC model. Many kernel interfaces and IPC mechanisms are abstracted as files so this is a rather important consideration. This is the model with an owner id, a group id and read/write/execute permissions for the owner, group members and other identities. It also comes with the suid and sgid bits, but I'll keep these off for now.

By default, UID 0 always bypasses DAC checks. This is because UID 0 has the CAP_DAC_OVERRIDE UNIX capability (see below). Processes that self-remove this capability will have to obey DAC, though most system files on your distribution are owned and writable by root anyway. Removing this capability may protect user files to an extent but will not protect the system itself. It is also very likely that a root user without this capability (and without the direct means to obtain other capabilities) can modify logind, your kernel image or other key files in order to corrupt or take over your system.

Linux Security Modules

On top of DAC checks, all system calls on Linux go through a pluggable kernel module that implements the Linux Security Module interface. Those could be used to deny privileges to root.

For instance, SELinux uses the concept of roles to this end. On all distributions' default policies that I know of, your login daemon will open your root sessions with a limited role, and you'd need to explicitly switch to a role called sysadm_r before you can perform most traditional root operations. You do need to write policy to prevent root from being root-like with other roles. Still, since LSMs allow you to write a mandatory access control policy, you can effectively limit root privileges this way. The nice aspect however is that you can effectively trap user:role tuples into their roles, and you can provide roles selectively depending on how one logs in. This would allow limiting the scope of a specific root account system-wide.

UNIX capabilities

I don't want to paraphrase the man page on capabilities but essentially, capabilities allow user identities to interact with specific interfaces of the kernel. For instance, CAP_CHOWN allows you to modify the owner of a file. By default, root has most capabilities enabled (if I recall properly, CAP_MAC_ADMIN or CAP_MAC_OVERRIDE are not enabled by default) and other identities have none.

You can however remove some capabilities from your own set, so you can as a root process transform yourself into an unprivileged process, as long as you have the CAP_SET_FCAP and CAP_SET_PCAP capabilities. Note that it's been argued that many other capabilities can be used to re-gain full privileges. I cannot find the list of such capabilities right now but you should be aware that you need to seriously think about how a capability you leave to your root processes can be exploited for further compromise.

Whilst DAC controlled file accesses, capabilities, arguably, control system call access and behaviour (and the MAC LSM controls both). You must read the manuals of many calls in order to understand what each capability does.

There is criticism of the fitness of capabilities for Linux. Kerrisk has argued in "CAP_SYS_ADMIN: the new root" that some capabilities are so heavily relied upon that having them means having full powers. This suggests that you cannot just get rid of the concept of super-user alltogether. You will need to be extremely privileged at least to boot and set up your system, and to provide certain in-kernel services. In MAC systems that offer strong opportunities for confinement, you often run into the issue of needing to re-obtain a privilege (for instance, on SELinux, you might need to change role to sysadm_r to perform a maintenance operation). Likewise, if you got rid of those capabilities, would you be able to (re)start new privileged services? Would the ability to do that not be equivalent to being fully privileged?

Linux User Namespaces

Namespaces allow you, very vaguely, to provide a different view of your system to processes run inside them. You can use mount namespaces to change what files a process and its children can see and modify, or network namespaces to provide different network interfaces and system configurations. This is useful for people who provide PaaS services, for instance. User namespaces allow you to map all of the user identities inside a namespace to a single one on the outside. This means that you can have a sub-system with a root user that can do whatever it wants inside the namespace and that is mapped to an unprivileged user outside the namespace.

What's the point of that exactly? If someone had an exploit on your kernel that allows them to escalate to root, the benefits of user namespaces are moot. However, if the exploit targets a suid binary, then an unprivileged process that gains access to root privileges inside its namespace will still be unable to affect the host OS. Note that confinement solutions like namespaces merely shift your boundaries of defense. Instead of proving that all your privileged processes are flawless and cannot be exploited, you must prove that a fully privileged process inside the namespace cannot affect the host OS via the communication channels you leave open between the host OS and the namespace. Ultimately if you need a privileged service inside your namespace to have access to a resource, then compromising that service will grant access to that resource.

What now? Can we provide entirely confined UNIXes?

All these methods above allow you to confine services to specific privileges (and with specific caveats, either in combinations (DAC+caps) or alone (LSM, namespaces). You can also combine them to provide defense in depth. However, the question of whether confining everything is beneficial is very independent from how you mediate privileges and represent the concept of full privilege (CAP_SYS_ADMIN, UID 0, un-namespaced privileged user, specific concept of your LSM).

When you write an operating system and you want it to be adapatable to its users' needs, you need to provide means to update and reconfigure it, and to run new services. If system maintenance involves operations such as updating your security services, access control policies, kernel and hardware modules, and so on, then you must either provide a way for a human user to act as a fully privileged actor, or you must have a third-party system that can adapt your OS and deploy the adapted version on top of your user's data. There are high security contexts where the latter might be desirable (and very frankly this is, conceptually, as simple as running a VM). In the case of general-purpose computing by a population of users that self-maintain their systems, however, you cannot get rid of fully privileged identities.

  • An interesting idea for the booting problem is OpenBSD's securelevel. Basically, it starts at 0, and everytime it is increased, some functionality is permanently locked down. It cannot be decreased, except by rebooting the system. That example is a bit crude, but could be expanded. – spectras Aug 17 '17 at 20:35
1

The init process has to run as root first. But fundamentally, the definition of root is not that it is a user with an id of 0, it is a process owner with the ability to access kernel routines. You could enforce a system where for AAA you run only commands related to the submitted jobs, but other than that there is no reason to remove the root user. The other thing is: it is not the root accounts that makes systems enticing, it is the fact that services running on the machines either have data or are able to transmit data that is the focus.

0

in fact all 'users' can be removed... kernels with just a static linked binary program in them performing one task work perfectly fine without any /etc/passwd file. ofcourse the concept of uids and euids still exists.

if your systems perform one specific task... just remove it all. file system, bootloader, libraries, the rest of the useless crap. and just run your task DIRECTLY in the kernel. (booting it from rom is a different story again ;) ofcourse if there are remote vulnerabilities in -your code- they can still gain access but there is no shell so they are limited to whatever code -they can insert- remotely.

-that being said- on -most normal systems- -most hacks- to uid0 take place not by bruteforcing passwords or by intercepting traffic... but by using all the crap built around it to -prevent that-. specifically sudo, traceroute, etc. most exploits from user 'www' to 'root' -require- a suid binary... and guess what su and sudo are.

once a system is finished... there actually is no appearant reason to keep all 'access' stuff around, after all, should there be a reason to fix things, one can update the entire image from development platform to deployment infra in flash or eeprom storage rather than 'access it' to run your editor/compiler locally or whatever.

  • the kernel doesn't know about 'user names' or 'passwords' or whatever other form of authentication you could possibly use. the kernel only knows uid numbers and gid numbers :P (the one thing that doesn't seem to work when linking directly into the kernel however, is the usual way of doing dns, as there seems to be no static version of libresolv ;) but who still needs dns anyway... servers definately don't need to know about hostnames and domains ;) – HRH Sven Olaf von CyberBunker Dec 12 '15 at 20:59
  • What do you mean by "statically linked binary in the kernel"? Are you talking about an embedded system where all the "work" it does is done by a kernel thread? e.g. you modify the kernel to not start anything in user-space at all? That seems worse from a security perspective. A security bug in a non-root static web server would let an attacker make TCP connections, but not raw sockets to run a packet sniffer or something. Or even to modify the server config files to affect things on the next boot. If they break into your kernel thread, then you're totally hosed. – Peter Cordes Dec 13 '15 at 2:04
  • 1
    @PeterCordes I think the point is now there's no such concept as "root", so technically you've prevented all means of privilege escalation to root? – immibis Dec 13 '15 at 23:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.