Parkinson’s Law of Security Privileges (or The Curse of Least Privilege)
Functionality expands so as to use all available privileges.
Parkinson’s Law postulates that “work expands so as to fill the time available for its completion”. It is commonly generalized to state “the demand upon a resource tends to expand to match the supply of the resource.”
It is easy to see Parkinson’s law at work all around us. We are all too familiar with how it applies to money. The budget (whether personal, corporate, or government) allocated for an expense always finds a way to get spent. Similar observations have been made about computing resources. Data expands to fill the space available for storage. Computing needs expand to make use of available cycles. Etc.
Not surprisingly, the law also holds for security privileges¹.
Parkinson’s Law of Security Privileges: Functionality expands so as to use all available privileges.
To see the law at work, consider the feature bloat of the nearest privileged component.
It is Parkinson’s Law that motivates the Principle of Least Privilege.
“Every program and every user of the system should operate using the least set of privileges necessary to complete the job.”
Saltzer & Schroeder, The Protection of Information in Computer Systems, 1974
As functionality expands, so does the attack surface. If we want to minimize the attack surface, we need to minimize functionality. To constrain functionality, we must restrict available capabilities.
In reality, the principle of Least Privilege is as much a curse as it is a design principle. Every program will operate using the least set of privileges necessary to complete the job. It is a warning that if the assertion is not satisfied by constraint of privileges, then it will be satisfied by expansion of the job’s scope. If it is not satisfied by the developers, it will be satisfied by the attackers.
This line of reasoning inevitably leads to a paradox: the components that need the highest privilege levels are also the ones we want to have the smallest attack surface.
This paradox leaves us uncomfortably reliant on self-restraint for keeping continuous expansion of privileged component functionality in check. Which, while worth aspiring to, is not a terribly dependable security principle.
There are, however, a few things we can do to help lessen the temptation. The key is to take a simultaneously expansive and high resolution view of what constitutes a capability, and then to relentlessly apply the Principle of Least Privilege.
There are three categories of capabilities to consider: logical, material, and algorithmic.
This category includes what we typically associate with security privileges: access permissions to system resources and sensitive operations (files, memory regions, privileged processor execution modes, etc.).
Somewhat unexpectedly, Parkinson’s Law implies that hierarchical layering of privilege levels — a common security pattern — may actually be an anti-pattern. If having higher (i.e. more sensitive) privileges is equivalent to having more (i.e. all the lower ones and then some) privileges, then it also becomes synonymous with more functionality.
Ideally, acquiring a specific sensitive capability should not require taking on a large set of other capabilities which may not be necessary. Approaches that utilize fine-grained capabilities that can be individually granted and revoked can help minimize potential for feature creep. SELinux is one example of such an approach.
Finer-grained temporal control of logical capabilities — restricting them to specific parts of the component life-cycle (e.g. initialization) — can be similarly useful.
This category includes physical development and computing resources: amount of available memory, storage, processing power, etc.
We are not accustomed to thinking about material constraints as something positive. There is a constant desire to improve performance, which often requires additional material resources. But limiting material capabilities can also be an extremely effective way of limiting functionality and associated attack surface of a sensitive component. After all, code that does not ship because it does not fit into available memory cannot be exploited. And I am confident that the amount of code running in supervisor mode in most systems would be greatly reduced if it could only run at half the clock rate of user mode.
The size of the development team is also a material capability. It is the original context of Parkinson’s Law after all — the amount of code developed will continue to expand to make full use of all available development resources. And code that is not written cannot be exploited either.
This category includes the complexity-theoretic capabilities of the component. Is it a Universal Turing Machine, capable of arbitrary computation, or something less powerful, like a Finite State Machine, with very limited computational abilities?
When it comes to security, this is perhaps the least recognized category of capabilities. At least outside of LangSec circles. LangSec may be many things to many people, but the part that always appealed to me is the Principle of Least Privilege applied to computational complexity. Don't use a Turing Machine when a Finite Automaton can suffice. Correctness can be proven for the latter, but not the former. More to the point, a more constrained computational model can support a lot less functionality.
Many anti-exploitation countermeasures, like stack canaries, DEP, and CFI, are effectively [attempts at] restrictions on algorithmic capabilities of the underlying software.
Like most security engineering, limiting capabilities is not something that can be easily done after the fact. Few would accept degradation of existing functionality and performance without a strong forcing function (like a catastrophic exploit). Capability budgets, across all the above categories, must be set during the initial design phase of the component and then strictly enforced throughout its lifetime. Because much like a gun in a Chekhov play, once introduced, a capability will have to be used.
 I’m using the terms privileges and capabilities interchangeably throughout this text.