Friday, March 2, 2012

UID Nobody and Mandatory Integrity Control

"Those who don't understand UNIX are condemned to reinvent it, poorly." -- Henry Spencer

The concept of nobody originates from Sun Microsystems and their work developing NFS. The uid was intended to represent an unmapped filesystem user with no special access (referred to as uid -2 in the original NFS RFC, but later explicitly named nobody). The plan was to prevent local privileged users from bypassing uid checks on remote shares, but the idea of a general purpose unprivileged user account appealed to many administrators and it's use expanded.

Sun embraced this idea, and Solaris still documents uid nobody as "Assigned to users or software processes that do not need nor should have any special permissions.".

The Solaris administration guide continues,
"The nobody user account is also assigned to software processes that do not need nor should have any special permissions. Some daemons, such as fingerd, run as nobody. If in.tftpd is enabled, it will run as the user nobody."

While motivated by well-meaning administrators, these organic changes were poorly thought out. The problem with this model is that by making these critical processes all the same unprivileged user, that user has ironically become one of the most privileged on the system. This unfortunate result is simply because nobody now has permission to interfere with the most critical processes on the system (via signals, temporary files, ptrace, and so on). The processes intended to be isolated for security, such as software installation and critical system daemons, are now all as vulnerable as the weakest link.

This is bad news. If your mailer daemon, name daemon and http daemon are running as the same uid, then a trivial cgi mistake means an attacker can read everyone's mail - the exact opposite of the isolation and compartmentalization that was intended. A better solution quickly presented itself: assign a unique UID to each daemon you would like to compartmentalize. With this improvement, a compromise of that daemon can no longer interfere with the operation of any other service.

The unique uid solution is used in most modern UNIX-like systems. Your sshd, sendmail, postgres, apache, bind, etc. all get their own user, hopefully compartmentalizing any potential compromise. In my opinion, this system is quite elegant.

Mandatory Integrity Control (Integrity Levels and UIPI) in Windows.

It occurs to me that Integrity Levels and UIPI are very similar to these antiquated (discredited?) privilege separation ideas from UNIX. Their growing use among important software (office software, web browsers, etc) is making "Low" integrity level a pretty exciting place to execute code, similar to the old concept of uid nobody.

Malware enthusiasts appear happy that we can prevent persistence across reboots for low integrity processes, which indeed is quite difficult if implemented correctly. However, it only takes one vendor using Integrity Levels incorrectly to break this assumption. Ironically, the first vendor I noticed defeating this property was Sun, the inventor of uid nobody. Their crime is storing Java patch executables in directories writable by Low processes, but I'm sure they won't be the only offender.

Still, I'm not sure I understand the "persistence" obsession. Nobody also had this property of being unable to persist across reboot, but it turns out attackers are quite happy to have ephemeral access to all your data. Frankly, if an attacker had access to all of my data, but I'm told not to worry because he can't persist across a reboot, this would be little consolation.

In conclusion, I'm not a fan of the design of MIC in modern Windows systems, I think a modern-UNIX-like solution, rather than an antiquated-UNIX-like-solution would be preferable.

I like the design of the Chrome sandbox in this regard, which effectively emulates these nice properties. I'm specifically talking about the Windows sandbox, I'm not such a big fan of the Linux or Mac sandboxes, although they do have some redeeming features lacking in Windows. The primary redeeming feature of the Linux sandbox is that it effectively reduces the kernel attack surface exposed to compromised renderers, but at the expense of a very inelegant design.

The good news is that my awesome friend Will Drewry is working on fixing that.

1 comment:

Unknown said...

I guess the thought behind appcontainer is to avoid this problem you point out. Each appcontainer has its own security identity.