The architects of Unix, Java and related systems have known that for a long time, which is one reason why these systems provide features not in a single program, but rather as separate processes that talk to each other over network protocols. That makes these multipronged systems a little more difficult to develop for but far more difficult to crack.
For an example of what happens without those complications in the architecture,
look to the most recent batch of security vulnerabilities in Microsoft software that have surfaced over the past weeks. Attackers can use a SQL query to overwrite just about any file on your system, thanks to a flaw in the design of SQL Server. It also came to light that you can trick Windows applications to do just about anything by sending standard Win32 API messages to these applications (see Shatter Attacks - How to break Windows). And you can exploit design flaws in Microsoft’s Office web components to gain administrator-level access to someone’s computer simply by embedding an ActiveX control in your web page.
This is a never-ending story, people. It’s almost impossible to enumerate all the reasons why Microsoft seems to get security wrong in areas where everyone else seems to get it right. The mistake made by Microsoft critics is that they focus on the buffer overflows and specific security holes. Microsoft’s design flaws go much deeper than that. The problem with Microsoft is that it integrates where others isolate.
For example, SQL Server has this “cool” feature that lets you create a dynamic link library (DLL) in any language and then use a SQL command to load and run that DLL as a stored procedure. As it turned out, however, Microsoft’s own out-of-the-box DLL-based stored procedures were vulnerable to buffer overflows, which made every installation of SQL Server open to attacks consisting of little more than a cleverly designed SQL query. Another SQL Server vulnerability allowed you to bypass all security checks on stored procedures simply by calling one stored procedure from another.
In both cases, Microsoft traded the safety of isolation for the convenience of integration. Here’s a better way Microsoft could have provided developers with the ability to run DLLs as stored procedures: Separate and isolate the process by creating a middleware product that runs custom DLL stored procedures. When you issue a query, it communicates the request to the middleware, which loads and runs the DLL with reduced privileges. Better still, run that middleware on another virtual or physical machine, which will provide you with even more isolation and safety. Finally, force every stored procedure to acquire its runtime permissions from yet another server process, such as an authentication server, and run that on yet another isolated virtual or physical machine.
These suggestions probably sound paranoid to a typical Windows developer or user, but this is precisely how a lot of Unix-based software is designed to work from square one. Even the graphical user interface on a Unix system is broken into two pieces, an X client and an X server, each of which can run with different privileges.
Security through multiple tiers and isolation is also one reason why I am very impressed with the Sun ONE architecture. It’s no accident that the Sun ONE range of products reads like a feature list, not a product list. If you run Sun’s directory server, metadirectory server, identity server, authentication server, portal server, web server and other processes in isolated environments, you increase the security of your system dramatically, because you can’t easily use one process to crack a weakness in another.
If you wrapped all those features into one software product — or, worse, a bundle of software products that share DLLs on the same machine — you’d end up with an interdependent mess of server processes that can steal each other’s privileges at the drop of a hat.