55

I am looking for ways to harden a linux system so that even when gaining full root access (through legit or non-legit means), some secrets remain inaccessible. But first a little background.

Many of the different linux security models (SELinux, TOMOYO, etc.) concentrate on limiting what processes can do by policy and making sure they do not need full root access. They aim to keep any exploits contained so other parts of the system can not be compromised. However, it seems that these do not directly tackle the case where full root has already been gained - or, even further, keeping secrets from the valid root user. It seems that usually these can be just turned off by the real root at runtime.

Another approach is to limit the ways of gaining full unrestricted root - for example not allowing all access to a remotely connected root user, but requiring a login from the physical console. However, this is not my goal either - the assumption is that any such protections have been overcome already and the root is as legit as it can be.

It is obvious that anyone with physical access to the machine can get everything stored on the harddrive and possibly also everything stored in memory. It is also obvious that if the root user has the power to modify binaries or kernel images, no security promises can be given after reboot. I am only interested in attacks that can be done without rebooting the system.

Also, during the start up process, secrets will most likely be transmitted in through many places and many security critical functions are needed. It is ofcourse great if secrets can be protected during the start up process as well, but what is enough for me is a step during start up where elevated privileges can be dropped and after which there are no ways of regaining them.

So, with these limitations, what are the ways on Linux to prevent the full root user from accessing some secrets?

  • Can there be files on the filesystem that are not accessible even to the full root by any means, but accessible to some processes? Some currently running processes, or even new processes started by the processes currently having access?

  • Can secrets be kept in memory by running processes so that even the full root can not gain access to them by any means? Can these secrets be transmitted to new processes by some means that the root cannot affect?

This is a hard question to write so that I get answers relevant to me, so I will try to edit the question to be more specific if necessary.


Obvious things coming to mind that need to be limited would be:

  • Disable access to /proc/mem

  • Disable access to /proc/<pid>/mem

  • Disable access to /proc/<pid>/fd/*

  • Disable module loading (only after some modules have been loaded, preferably)

  • Disable ptrace access to any process

Nakedible
  • 4,531
  • 4
  • 26
  • 22
  • Just as an example, here's a rather recent patch adding once again one variant of capability dropping: https://lkml.org/lkml/2011/7/19/231 – Nakedible Oct 02 '11 at 17:10
  • 3
    *"I am only interested in attacks that can be done without rebooting the system."* - This seems like it opens up a dangerous escape hatch for an attacker: simply cause the system to be rebooted. – D.W. Oct 02 '11 at 18:53
  • 4
    Quite true, but in my use case that isn't really relevant. In my use case, the system is running on Amazon EC2 - nothing persists over reboots. In addition to that, the secrets will not be given to the system automatically - so the secrets are lost permanently in the reboot. – Nakedible Oct 02 '11 at 19:16
  • 4
    Thanks for the explanation. Perhaps it would be useful to ask yourself the question: do you even need a root user in the first place? For instance, have you considered setting up your EC2 VM so that no one can log in as root? That might lead to a simpler solution to your particular problem. I wonder if, by allowing us to think outside the scope of the particular question you've posted here, we might be able to find a better solution for you. – D.W. Oct 02 '11 at 21:19
  • Shameless Plug Warning. There are commericial products that provide this functionality readily. Trustifier KSE provides this for Linux. Raytheon Trusted CS is another. – Ahmed Masud Aug 02 '14 at 20:43
  • *machine thief* is even more powerful than *root* – Skaperen Sep 07 '15 at 09:26

8 Answers8

32

Actually, it is possible to restrict root if one is prepared to define such a restriction as fundamentally trusting the operating system. This can be done using SELinux (that I know of) and presumably other such systems. The best such example I have seen of SELinux used in such a way is Russell Coker's Play SELinux Machine.

As a brief overview of how it works, the name "root" is not special in Unix. The UID 0 is. UID 0 is taken to mean "trust everything I say". This applies specifically to the standard access model used on Unices, Unixen or however you pluralise "Unix".

LSM, or Linux Security Modules, allows you to hook into just about everything and audit/deny actions as you see fit. In the case of SELinux, SELinux permissions are checked after Unix permissions, so your flow looks like this:

Event ----> Has Unix Permissions? ---> Has SELinux Permissions? ---> Let it happen

The next stage to understand is that there are, or have been historically, different versions of the SELinux Policy. Before I get into that, understand that in SELinux:

  • inodes have types, suffixed _t, which might also be called domains; and
  • users have roles, suffixed _r.

Combined, they control what action a user in a given role may do, and what a process in a given domain may do.

Now, there are three main SELinux policies:

  1. targeted. This is the default policy for desktops like Fedora. The idea of targeted is that critical system services and daemons are run in domains, but a lot of what you the end user does is run in unconfined_u:unconfined_r:unconfined_t. No prizes for guessing what that means - if Unix permissions work, SELinux is effectively pass-through.
  2. strict. This policy involves removing unconfined_u entirely. This is not an easy process, especially on the Linux desktop (i.e. init 5). Specifically, the X11 security model is not great and often requires unconfined_t for some applications. You can do this, but I would expect working with X11 to be harder (although not impossible) especially when executing GUI applications that require root. There is a project underway to provide support for SELinux-like functionality in X, called XACE (X Access Control Extensions).
  3. MLS. MLS stands for multi-level security and means the end of the permission string: user_u:system_r:httpd_content_t.s0-s2:c5-c7, i.e. those s and c numbers actually mean something. Specifically they form a no read up, no write down setup such that unless the process is running as a certain level, the information they can see will be limited. The idea of this level of information is to protect classified assets—SELinux was originally developed by the NSA, presumably for this purpose.

So that's your background. Now, according to the web pages (see FAQ) root is UID 0 on the play machine; however, root is set to run as user_r and not sysadm_r in the strict policy. This means the user will not be allowed to execute administrative functions from the shell.

What would be interesting to know, then, is the status of the other processes that do require root. Presumably such processes have been appropriately labelled and have policies that allow them the access they require. The question then becomes how do you administer the system and can any of these processes launch a shell in that user's context. If that can happen, you can still manage an exploit.

Since the play machine is currently down (at time of writing), I'm working on assumptions here; but essentially, you would need a process running in sysadm_r and with UID 0 as your target for an exploit. Assuming such a process exists and is exploitable, you could still get to root. As for still being able to admin via root, there are two options that I can think of:

  • Either there is a trusted transition of some sort that means root then can transition to sysadm_r (less secure) or
  • On different runlevels, a different policy applies, so to admin the machine one sets the runlevel to 1 and the policy does not restrict root. I'm guessing here.

Summary

If your question is "can I easily and safely do this now?" the answer is no. If your question is "I am prepared to learn about SELinux, get down and dirty with my distribution and put up with quite a lot of things not working" the answer is it is possible to constrain root much more than your average install. That said, this does not in any way make you invulnerable to exploits—it does not make it impossible for a user to circumvent this extra access control either in software or physically.

So yes, you can make things invisible to root; however, the extra technical burden aside, the same caveats apply as to any access control setup on any normal user—there is no silver bullet.

Oh and blatant self-promotion: you might like my blog post on storing secrets in software. It's on the security stackexchange blog, so I don't feel so bad about promoting that. Essentially, as you can see, there are mechanisms to make life a lot more difficult for an attacker (and you), but in the end, it's a case of "turtles all the way down" i.e. fundamentally impossible to do.

forest
  • 65,613
  • 20
  • 208
  • 262
  • I think the plural of unix is unix, like sheep, or deer. – chown Oct 02 '11 at 18:16
  • Hmmh, I've studied this approach some, but it seems the play machine approach hinges on limiting the power of root for all the mundane administration tasks as well. SELinux in general, though, seems to be able to limit most of the attack vectors, but this needs more investigation still. Thank you for the long answer! – Nakedible Oct 03 '11 at 13:11
  • Your answer is essentially what I would have said. Use Mandatory Access Control (MAC), which SELinux provies. AppArmor is another MAC implementation which is available on SUSE, openSUSE, and Ubuntu. TOMYO is yet a third MAC implementation redily available to Ubuntu and CentOS. Remember that all of these are merely mechanisms to enforce a security policy and without a well designed security policy they will all fail to provide the desired protection. – this.josh Oct 04 '11 at 07:20
  • @chown, I think it's "Unix Systems" – Kaz Wolfe Aug 04 '14 at 00:46
  • 3
    The plural of Unix is Unices, and less commonly, Unixen. See http://www.dictionary.com/browse/unix and the end of https://en.wikipedia.org/wiki/Unix#Branding – forest Apr 07 '16 at 03:00
  • @forest although true, I'll never in a million years equate seeing "Unices" or "Unixen" to "Unix". Ever. Complete failure in pluralization. – Nelson May 20 '19 at 08:21
14

I've had to tackle this problem before, when approached by a client wanting to keep 'private messages' secure between users on a website. It's possible to protect some data in some circumstances, but this is reasonably limited.

My approach was to simply store an encrypted version of the note on the server, and have it sent to them (once authenticated of course), then decrypt it entirely client-side. This means that even in the event of a full compromise of the server security (i.e. root access), the notes remained secure. The limitations of this however:

  • Protected data is only secure up until the point of compromise, and no later. Depending on the method used to encrypt the information, a rooted server may trick the user into revealing the decryption keys (JavaScript injection, or for native GUI clients, issuing a compromised client update) or otherwise intercepting the decryption keys (if the keys are based off the same method as authenticating the user, such as a password, they can be intercepted during the server-side authentication process).
  • Transmission requires perfect forward secrecy otherwise the encrypted data could be intercepted, stored, and then decrypted post-compromise as discussed above.
  • This doesn't protect anything if the client is also compromised. Unless you're processing encrypted data entirely in your own head (and if you can, you deserve a trophy or something), you're going to be giving sensitive data to something, and nothing is perfectly uncompromisable.
  • There is no way of using this data server-side (i.e. for indexing purposes) unless decryptable/plaintext metadata is stored alongside, which may reveal additional information.

Essentially this limits the potential uses for this scenario, and there are still weaknesses, but it is possible for it to work in some situations. Password hashing is a (reasonably) successful example of 'root compromise protection', in that even physical access won't reveal the passwords of a user (except of course if that password is transmitted post-compromise).

There's other examples in this thread that are worth looking into also, but give some thought to the client-side processing scenario, using the server simply as a secure storage service.

TC

TC Fox
  • 535
  • 2
  • 8
  • 1
    Great answer! This makes the security of the server irrelevant, and thus makes root's level of access relatively harmless to overall system security. I think this kind of direction may be more promising, in application domains where it is applicable. – D.W. Oct 03 '11 at 01:50
  • Unfortunately, this approach isn't relevant to my needs. Great idea otherwise, though. – Nakedible Oct 03 '11 at 06:47
  • 1
    Thought that could probably be the case. Still, it was worth mentioning, on the off chance it might spin off a similar idea that could help. And it seems to have helped others! :) – TC Fox Oct 03 '11 at 07:10
6

Can there be files on the filesystem that are not accessible even to the full root by any means, but accessible to some processes? Some currently running processes, or even new processes started by the processes currently having access?

No. When a process can access them, so can root. If you want to do such things, you'll have to heavily modify the whole system, possibly a system which boots an immutable kernel from some readonly device and which denies root certain file/memory accesses while permitting them for other users which root can't impersonate.

Can secrets be kept in memory by running processes so that even the full root can not gain access to them by any means? Can these secrets be transmitted to new processes by some means that the root cannot affect?

No. See answer above.

You can't, by definition, restrict access for root. If you limit root's access then it isn't a root user anymore.

If I wanted to deny root access to secrets, then I'd try to hide them. Cryptographic containers, maybe hidden in swap memory or somewhere else and only accessible with a password or some other sort of steganography. It's damn hard to find a needle in a haystack, although not impossible.

Falcon
  • 691
  • 6
  • 7
  • 6
    Incorrect, the Linux kernel has several ways to restrict what root can do - and it is still called the root user. For example, if file permissions disallow access to a file, but root can access it, it is actually the capability CAP_DAC_OVERRIDE that allows it. If the root does not have this capability, even it does not have that power. – Nakedible Oct 02 '11 at 17:08
  • 1
    @Nakedible: That's interesting, I didn't know that. But I still question whether these capabilities can be universally removed from the root account in order to provide fine grained control about what root can access and what not. Can they? – Falcon Oct 02 '11 at 20:17
  • Yes they can, but the details are a bit fuzzy. In the 2.4 series kernels, one could simply echo a bit to /proc/sys/kernel/cap-bound to disable, say, module loading system-wide. Nowadays, capabilities are only per process, so it is a bit trickier - which is mostly what I'm asking here. There's just too many variables and too little documentation so I'm puzzled as to what is the correct approach. – Nakedible Oct 02 '11 at 20:21
  • One more link about this: https://wiki.ubuntu.com/Security/Features – Nakedible Oct 02 '11 at 20:23
  • 1
    @Nakedible - My understanding is that POSIX capabilities don't restrict what the root user (uid 0) can do. Rather, they can be used to restrict particular processes that are running with euid 0. Thus, as far as I know, I don't think it's entirely accurate to say that capabilities provide a way to restrict the root user. – D.W. Nov 27 '11 at 21:20
6

There are a number of indirect ways through which root can end up executing arbitrary code. You can disable them, and indeed some security frameworks might disable them, but they cripple the ability of root to perform administration tasks.

For example, root can read and write to disks directly, bypassing all manner of filesystem permissions. You can take away this ability, but then root won't be able to move a full filesystem to a new disk in an emergency.

Root can load kernel modules, and thereby can do everything the kernel can do. You can take away this ability, but then you preclude loading drivers for hot-pluggable media. (This may be desirable in .001% of unix installations, but it's not the general case.)

Root can update executables that allow users to log in, such as login or sshd. These daemons handle user authentication, so if you control their code, you can inject a backdoor. You can take away this ability, but then root won't be able to perform security upgrades.

Root can create and remove users and change authentication credentials: if you can edit /etc/passwd to add an account, you can also edit it to temporarily make an account passwordless. You can remove this ability by making some files read-only even for root, but then you'll end up with a system where you can't create or remove user accounts without rebooting.

Security frameworks effectively create limited-root users which are root only in a subset of the system — root only in a virtual machine, not in the “real” system. This limited-root loses the possibility of performing administration tasks on the real system. I think virtualization is what you're after.

Gilles 'SO- stop being evil'
  • 51,415
  • 13
  • 121
  • 180
  • I realize that in general this isn't a really attractive approach to security. However, in this case, I don't necessarily care about bypassing filesystem permissions, or updating executables handing login or anything like that. I do care about module loading, but I don't need it after system startup. I'd hope to achieve a root which can do *almost* everything, except dig out the secrets from some part of the system. For that, the ability to use gdb, for example, might be lost - but it depends on the specifics if that is acceptable. – Nakedible Oct 02 '11 at 20:17
  • How does virtualization solve the powerful administrator problem differently from the way an OS solves the problem? The virtual machine still needs to run on a real machine somewhere. – this.josh Oct 04 '11 at 07:25
  • 1
    @this.josh Root has a lot of abilities, and it's hard to contain them in a way that doesn't leave an escape route. The VM approach means giving someone unbridled root access in a VM (allowing them to set up networking, install and update programs, set up filesystems, etc.). Root on the real machine is reserved for people who do hardware maintenance (and so have access to the hardware anyway) and VM provisioning (which is hard to limit, though in principle TPMs could link a hardware security module with security in the VM bypassing the host administrator). – Gilles 'SO- stop being evil' Oct 04 '11 at 08:32
3

Like Falcon said, the root user by definition has access to all of those things, or it is no longer the root user.

The kernel controls all of the hardware, so once you are root you have the same access. You really need virtualization so your root user is only root for the virtualized OS it is running on and some Hypervisor sits outside of that root. (not to say that hypervisors aren't exploitable, but what you are trying to do is equivalent to this).

Bradley Kreider
  • 6,182
  • 2
  • 24
  • 36
  • 3
    Incorrect, the Linux kernel has several ways to restrict what root can do - and it is still called the root user. – Nakedible Oct 02 '11 at 17:05
  • 1
    @Nakedible, are you sure? My understanding is that, for the most part, these can be used to restrict particular processes that would otherwise have full root privileges (i.e., particular processes running with euid 0), which is not exactly the same as restricting the root user itself. Have I misunderstood? – D.W. Nov 27 '11 at 21:21
3

This is relatively easily accomplished by using a "two key" selinux system: root has no permissions to do anything, and some other user without root permissions does, so to change stuff, you first need to be the non-root other user, then you "su" to root to make the change.

Neither user in isolation can do or see anything.

I'm using this. It works really well.

cnd
  • 131
  • 1
  • you are still able to access other users data as root. The fact that you need an extra (user specific) password to become root seems irrelevant. – jiggunjer Apr 06 '20 at 15:49
2

The actual need is not well defined in the question, but two potential solutions what is alluded to have not been mentioned:

  • Containers
  • HSMs

Containers - which are of course just a more architecturally-sensible approach to what was being done piecemeal with tools like jails and SELinux - may be of relevance in the context of a reframing of the question - is there a way that a unix-like logical system can be exposed to attackers such that it may be root-compromised yet secrets on the physical system are still protected. With containers we are getting close to this goal. A recent paper by security group NCC is worth a read: https://www.nccgroup.trust/globalassets/our-research/us/whitepapers/2016/june/container_whitepaper.pdf

HSMs are hardware encryption devices that prevent the retrieval of decryption keys via physical or logical methods, so may be an answer to the question reframed as- I have secrets that I have to decrypt securely, what do I do with the keys.

dijksterhuis
  • 103
  • 4
Jonah Benton
  • 3,439
  • 12
  • 20
2

Have you tried Grsecurity? It can effectively restrict root users in every possible way. https://grsecurity.net/

Grsecurity, coupled with PaX makes your box an impregnable fortress... if you do it right

forest
  • 65,613
  • 20
  • 208
  • 262
Jauzsika
  • 137
  • 2
  • I have looked at grsecurity briefly and it seems to do something similar at least. However, I was looking for the specifics - some way to achieve what I want, and explanations on what the boundaries of the security solution are. – Nakedible Oct 02 '11 at 19:13
  • 1
    Well, GRSecurity is quite complex, so there is no 1 minute solution for your problem. Check the unofficial GRSEC book and take a look: http://en.wikibooks.org/wiki/Grsecurity – Jauzsika Oct 02 '11 at 19:14
  • Also, I would prefer something that is included in the mainline Linux kernel - however, if there's nothing there that works, I am willing to trying out patches. – Nakedible Oct 02 '11 at 19:17
  • Well, SELinux is included and it definetly gives you a false sense of security. Also uses some of the solutions from GRSec/PaX. Use GRSec/PaX if you want security. – Jauzsika Oct 02 '11 at 19:19
  • 3
    -1 for using the word "impregnable" in a computer security discussion. There is no such thing and you know it. – Shadur Oct 02 '11 at 19:27
  • Shadur, have you read the whole sentence? "impregnable fortress... if you do it right :)." Anyway... – Jauzsika Oct 02 '11 at 19:28
  • Grsecurity is a form of Mandatory Access Control (MAC) similar to AppArmor, SELinux, and TOMYO. MAC is a solution to the powerful administrator problem, but it has a high cost in terms of designing, seploying, and updating security policy. – this.josh Oct 04 '11 at 07:29
  • Grsecurity is an RBAC based system. If you run a dog breeding business you don't really need it :))). – Jauzsika Oct 04 '11 at 12:51
  • @this.josh Grsecurity _contains_ a MAC framework, but it is a very small part of the overall protections provided by grsecurity. – forest Apr 07 '18 at 04:15