The Elegance of Simplicity
Insights into the Mind of a Security Professional
Have you ever wondered why some solutions to security succeed, while others seem to fall apart? To the untrained professional, the natural approach is to build on top of and add to existing solutions, thinking that by adding more security layers they are then making the problem so complex that few people can pick it apart. For the trained professional though, this comes across as a foolish endeavor, as pouring in too much complexity ultimately widens the attack surface and gives an attacker a larger pool from which to attempt to break the system. As counterintuitive as it may sound, for a security professional, less is more, so long as everything is kept at its simplest and no simpler.
The Fox and the Hedgehog
To help illustrate this point a bit, there's an old parable called the fox and the hedgehog. For those unfamiliar with this tale, it goes something like this: Once upon a time, a fox encountered a hedgehog. Startled, the hedgehog rolled into a ball. Fox then laughed at this sight, and said: "Hedgehog, that is the silliest thing I have ever seen. Surely if you were as clever as I am, you would have hundreds of ways to protect yourself. For instance, I might zig and zag, or run into a burrow to hide, stand my fur on edge to look bigger, or any number of other tricks. With a mind like mine, you wouldn't need to rely on such a silly tactic for defense." To which the hedgehog replied saying: "While that may be true, rolling into a ball has always worked for me. I live a simple life, and while I might not be as clever as you, I do think that you are too quick to dismiss how effective rolling in a ball can be." The fox then left, snickering about hedgehog's response. "There's just no way that hedgehog is wiser than the cunning me."
Later on, a hunter entered into the woods with hunting hounds. Hedgehog, upon hearing the hounds coming, rolled into a ball. The hounds batted at hedgehog, trying to find some way to make him unravel to no avail. No matter how the hounds tried, they could not get hedgehog to break his defenses. Fox, upon seeing this, snickered once more at the sight. "Surely hedgehog is as good as gone." the fox thought. After a while though, the hounds gave up on hedgehog as they noticed the smell of fox sitting nearby. Getting nowhere with hedgehog, the hounds immediately changed their target to the fox. Fox tried to zig and zag to throw off the hounds, but to no avail, as he could not hide from the hound's noses. Fox then attempted to enter a burrow to try to hide from the hounds, but alas, the burrow was occupied, and he was pushed out by its owner. Finally, the hounds cornered fox. Fox, using his cunning, then attempted to stand his fur on edge to look bigger. This initially scared the hounds so much that they began to howl, or so fox thought. Shortly thereafter, the hunter arrived with his gun and shot that fox.
The moral of this tale is that there is an elegance in less being more. In engineering, the term KISS is often used, standing for keep it simple stupid, to explain the same principle. In security, we will often talk about good enough security and measure success by calculating the cost of implementing a security layer, then comparing that cost to the annual loss expectancy, and define success by reducing that value as much as practical without incurring more costs than necessary to do so. The simpler the solution is to stave off large losses, the better it is for the company's bottom line. When viewed from this vantage point, it becomes a bit clearer why simple solutions to large problems is the ideal outcome.
Was the Fox Right All Along?
Now at this point, you might be thinking that the parable might be flawed for many different reasons like how the hunter was obviously targeting foxes and not hedgehogs, or that hedgehog’s solution to defense is not one which fox could adapt, making it so that fox’s relying on his cunning to provide his defense is not such a bad idea for his situational needs, to which you’d be correct.
Taking this insight into consideration, how can both views be correct? Both fox and the hedgehog had valid insights into what security practices work, but it all came down to their implementation. Hedgehog had a simple approach that he knew was effective because his quills would provide all the defense that he’d ever need. Fox, on the other hand, was a little less organized on his approach. If he had instead quickly understood what the threat was to him, he might’ve been able to come up with a strategy like running down to the river, swimming a distance until he can be That said, fox’s scoffing at hedgehog’s approach, while ultimately wrong, had some kernels of truth in it. Providing a defense in depth where you don’t rely on just one solution to protect you is also a smart approach to securing yourself. Had the hunter been hunting hedgehogs instead of foxes and known the approach that hedgehog had been using to secure himself, the hunter could’ve developed a strategy equally as valid for breaking hedgehog’s defenses. If hedgehog didn’t have another solution beyond rolling into a ball to protect himself from the hunter, then any attack which is specifically targeted to exploit weaknesses in hedgehog’s strategy would succeed. This leads to many defenses in the real world adapting approaches of both the fox and the hedgehog, utilizing the best of both approaches.
However, it is important at this point to not forget either the wisdom of the fox or the hedgehog and to seek a balance between both. Too often when we think about securing resources, we dismiss hedgehog’s simplistic approach and think like the fox that the more layers we add to our defense, the more secure we are. So long as each layer is kept simple to understand, there’s no issue, right? Well, yes and no.
While having multiple simple layers ultimately is better than one monolithic and complex approach, a balance must be struck between simplicity and complexity. If we depend too heavily on one approach like the hedgehog, there are scenarios in which that approach will fail and we will ultimately find ourselves exposed to danger. Likewise, if we have too many layers operating at the same time, we can find ourselves in a situation where we are paralyzed by the information pouring in and make suboptimal choices. Therefore, it is much better to have multiple layers that employ a variety of unique and strong defense techniques but keep their overlaps to a minimum. We ultimately want many different types of hedgehogs to defend ourselves, but not so many that we find ourselves to have become foxes.
A Case Study in Simplicity
Now that the parable of the fox and the hedgehog has been fully analyzed, let’s move on to a simple scenario that analyzes the differences in approaches to file permissions as implemented by Unix and Unix-like systems, and the approach used within Windows. The goal here is not so much to declare one to be superior to the other, but to outline how much easier it is to secure things when we keep things simpler.
Both approaches involve the use of groups, and the basic permissions of read, write, and execute. In Unix, this is where the granularity stops. Permissions boil down to four different octets, one for the type of resource it is (link, directory, or file), another for the specific user, another for those who are in the user’s group, and another for everyone else.
In Windows, it is a rather similar situation. There are permissions for full control of files, reading, writing, modifying file permissions, and read and execute, which can apply to individuals and groups. If this was as complex as permissions get, then there wouldn’t be much to comment about in these minor differences. However, Windows goes further with more advanced permissions granularity. In addition to these basic permissions, it is also possible to restrict folder traversal/file execution, list folder/read data, read attributes, such as hidden, read extended attributes, which are program specific, create files/write data, which allows for overwriting existing contents of the file, create folders/append data, which allows for writing data to files or directories, but not for overwriting existing contents, write attributes, write extended attributes (again, program specific permissions), delete subfolders and files, delete, which is a subset of delete subfolders and files that doesn’t allow for deletion unless explicitly allowed, read permissions, change permissions, and take ownership. Each attribute is then either an explicitly or inherited deny or allow.
At first glance, this granularity could be seen as being an improvement over the very basic permissions that Unix offers, but on closer inspection, Windows permissions beyond the basic permissions can lead to all sorts of potential pitfalls. For instance, if a directory has the delete subfolders and files permission set to explicitly allow, but a file inside that folder has an explicit delete deny, which takes priority? Clearly it is intended that that subfile is not supposed to be deleted, but its parent directory doesn’t know this and allows for a broader deletion profile. While there is a greater level of granularity allowing for more control, there is also more room for making mistakes like this, and it isn’t as clearly defined for what permissions should do as in the Unix approach. Again, this is not to say that the Windows permission structure is inferior to the Unix one, but that by allowing for more granular permissions like it does, it opens itself up to being misused in more ways than a simpler approach might allow.
While there are benefits to both the fox and the hedgehog approaches to security, trying to be too much like the fox leads to unexpected pitfalls cropping up over time. Secure systems by design tend to favor an elegant simplicity like the hedgehog, even if they employ multiple strategies like the fox does to secure themselves. Designing a secure system requires balancing the amount of complexity expended while applying the principles of KISS. While it is tempting to overdesign solutions to try to stave off as many different attack vectors as possible, it is important to continually evaluate each layer over time to determine its necessity and value added to your security approach, so that secured systems can be as simple as possible, but no simpler. The end goal being that such solutions end up being composed of a variety of hedgehogs, but not devolve into being one giant fox. That way, each layer does their one job well and effectively, without opening themselves to a wider attack surface. As counterintuitive as the approach may seem to reduce complexity to improve security, often doing less is more.