on
The Myth of Least Privilege (or why we love equivalence classes)
Just about any Mandatory Access Control (MAC) advocate will tell you that their ultimate security goal is least privilege. Least privilege has become a metaphorical holy grail in the security industry. Least privilege, in its unadulterated form is giving each user, process and so on the exact access it needs and no more.
The problem with the idea that this is achievable is that modern systems are very complex. Every application would practically have a catalog of objects that it needs to access, particularly when you get onto the desktop. Every library, man page, binary, configuration file and user file would have to be explicitly granted access. This brings up some obvious problems, particularly the amount of rules that would be required on modern machines but also more subtle ones; for instance, files that are not known, or in existence, at the time of the policy creation. Shared resources are an issue as well as user home directories and temporary files. A user’s mail client obviously can be restricted to a user’s mail directory and be restricted from the rest of the user’s files but a word processor needs practically free reign in the user’s home directory, with the obvious exception of private data like ssh and gpg keys. Since a policy writer doesn’t know what files a user would open with their word processor it must essentially run with the users normal privileges, which makes it able to access anything the user can, clearly not least privilege. Users, especially on desktops, tend to do very unexpected things which adds more difficulty to the equation.
The argument could be made that non-networked applications need not run with their own privilege set but given the complexity of current applications even word processors are susceptible to malicious data that could exploit the user’s privileges, particularly in the information rich world we now live in.
Another problem is that modern software is often not designed with security in mind. There are hundreds of examples of applications which ask for more access than they need. Many of these applications even work fine without the access but request it anyway. For examples of this look at all the dontaudit rules in the SELinux policy. Without control of all the software on the system we are destined to put up with these least privilege violations. Just using open source software is probably not enough due to the amount of effort and time to clean up the issues (and maintain patchsets when upstream authors aren’t compelled to care about said issues)
On embedded systems with very small kernels and little software least privilege might not be difficult, particularly when a single company or person controls the source code in its entirety. Systems like these generally don’t have users either. This eliminates the complexity and the unexpected behavior of users and thus makes least privilege much easier but general purpose computing remains a problem.
The real world solution to this problem is to use equivalence classes on subjects and objects. It doesn’t really harm the security of a system to treat all the libraries in /usr/lib the same. Any application that needs to read libraries can be allowed to read all the libraries on the system while still being confined to the resources it needs elsewhere. Even if the application loads a library that it shouldn’t, the application will still be confined to the resources that it’s intended to use. Other objects can be grouped together as an equivalence class as well. Most binaries in /bin and /usr/bin will actually not run with more or less permissions than the user. For example, trying to give /bin/ls a different permission set than the user running it would mostly be unproductive. Common UNIX commands such as cp, mv, ln, ls, and so on should be treated no differently than the user running them. These equivalence classes make mandatory access control easier to implement and policies much easier to write but using equivalence classes is clearly a conflict with least privilege.
Least privilege on modern systems would result in an unwieldy number of rules and would likely cause many problems with applications not being able to access the resources they need. Experience has shown us that users also become startled when things they are accustomed to doing suddenly don’t work (such as setting system passwords via apache!). Equivalence classes, such as types in SELinux, provide a layer of abstraction that makes strong security far more viable at the cost of more privilege than absolutely necessary. You needn’t worry though, equivalence classes can be as general or specific as necessary and the security policy treats the resources as equivalents at your discretion. The bottom line is that unless your entire system has 5000 lines of code you don’t really want least privilege. There are many appropriate (and inappropriate!) security models depending on your system architecture and choosing one is the most important step toward securing the system. I plan on writing about choosing security models in the future so keep your eyes out for that.