Mitigate Security Risks by Minimizing the Code You Expose to Untrusted Users
This article discusses:
- Identifying and reducing attack surface
- Reducing the amount of code executing by default
- Reducing the volume of code accessible to untrusted users
- Limiting damage if hackers do attack your code
This article uses the following technologies:
Windows Server 2003, Windows XP, Security
Code fails. It's a sad fact of life. It is these security failures and code vulnerabilities that interest me most. In the industry, we worry a lot about improving code quality. While code quality is exceptionally important, most code will eventually fail so we cannot focus exclusively on getting the code right. Imagine for a moment your code is perfect. It's only perfect by today's standards—a snapshot of best practices at the time it was developed. Yet the vulnerability research landscape is constantly evolving. Four years ago, integer overflow attacks were almost unheard of; now they are the attack de jour! Imagine broadening the scope to all the code you've ever delivered to customers.
You need to change your outlook from "my code is very good quality" to "though my code is the best it can be with today's knowledge, it likely still has security defects." Once you get into this state of mind, the attack surface reduction (ASR) philosophy becomes easy to digest. The attack surface of an app is the union of code, interfaces, services, protocols, and practices available to all users, with a strong focus on what is accessible to unauthenticated users.
The core tenet of ASR is that all code has a nonzero likelihood of containing one or more vulnerabilities. Some vulnerabilities will result in customer compromise. Therefore, the only way to ensure no customer compromises is to reduce code usage to zero. ASR is a compromise between perfect safety and unmitigated risk that minimizes code exposed to untrusted users. Code quality and attack surface reduction combined can help produce more secure software. Perfect code cannot do it alone.
Remember, never lose track of your customers: they're the people who will need to apply any of your security updates. If the code has a flaw, does your customer have to patch the 4 machines using the faulty functionality or the 400 with the software installed by default? It will make a huge difference to the person handling it.
In this article, I will explain a simple process to help you reduce the attack surface and to help improve the security of your applications. ASR has three main goals:
- Reduce the amount of code executing by default
- Reduce the volume of code that is accessible to untrusted users by default
- Limit the damage if the code is exploited
Reduce the Amount of Running Code
This is the easy step—just turn off some features! Apply the 80/20 rule and ask yourself, "Do 80 percent of my customers use this feature?" If the answer is no, then turn it off and make it easy to turn the feature back on. In Windows Server™ 2003, we turned off over 20 services because if the service is not running it cannot be attacked. For example, the Web server, IIS 6.0, is not installed by default; when you do install it, it serves only static files by default. All forms of dynamic Web content are opt-in. Therefore, if there is a security defect in WebDAV, for example, the only affected customers are those actively using IIS and WebDAV rather than all users of Windows Server 2003.
Another example, outlined in Microsoft® Security Bulletin MS04-020, "Vulnerability in POSIX Could Allow Code Execution," does not affect Windows® XP or Windows Server 2003. Applying the 80/20 rule, 80 percent of the users do not use the POSIX subsystem (to be honest, I know of no one who does!), so it was simply removed from the operating system.
Obviously, turning features off can cause applications that used to operate correctly to fail, and you may add complexity when people want to use the feature. Now I'm a security guy, so I always err on the side of security, but I'm painfully aware of the impact on nontechnical users when applications fail. You could make an extremely secure system by running no code whatsoever, but that wouldn't be very useful, now would it?
The good news is ASR is not just an "on or off" proposition; you can reduce attack surface by limiting who can access the code once it is running. This has an interesting side effect: many features are still usable, but are inaccessible by attackers. That's next.
Action: Apply the 80/20 rule to all functional areas. Do 80 percent of your users use the functionality? If not, consider turning it off.
Reduce Access to Entry Points by Untrusted Users
Going back to the IIS example, another way of reducing who can access WebDAV functionality on a given Web site is to restrict access to any site using WebDAV. By default, most Web sites are accessible to all users (regardless of their intent), so any attacker on the Internet could probably exploit a defect. However, if the Web server limited access only to trusted users, or users on a specific subnet, then fewer users could take advantage of the defect. This is good because the code works for those who require the functionality. One of my favorite examples is the firewall in Windows XP Service Pack 2. When we turned the firewall on, one very common scenario broke: the small home network, where a central computer acts as a file and print server for other computers in the home. Disabling this functionality by shutting down the ports at the firewall was simply not an option as it breaks potentially hundreds of thousands of users. The tradeoff was to open the ports, but only on the user's local subnet. Valid users can access files and print them, but the bad guys cannot. See the Sidebar Windows XP Service Pack 2: Information for Developers for more information on Service Pack 2.
Another way to reduce the number of people who can communicate with potentially vulnerable code is to authenticate the caller before she can access the code (of course attackers will try to attack the authentication code, too, but that's a story for another day!) Again, this is something we did in Windows XP SP2. We limited access to remote procedure call (RPC) endpoints to valid Windows users; anonymous users (potential bad guys) cannot access the endpoint and cannot therefore attack the code. Remember, most bad guys are unauthenticated, and by raising the authentication bar a little you can eliminate a large population of potential attackers. This is something I do with every Web server I install—one of the first settings I disable is anonymous access.
Action: Restrict access to network endpoints used by your application to the local subnet or IP range.
Action: Limit access to network endpoints using authentication. Simply validating the user reduces your component's attack surface.
Reducing Privilege to Limit Damage Potential
Let's assume for a moment your code does have vulnerabilities, and you decide not to limit access to the code through some of the simple measures I've just suggested. You can still reduce the damage potential by operating the code with reduced privileges. Let's look at another example. On June 8, 2004, Microsoft issued a security bulletin (Crystal Reports Web Viewer Security Update for June 2004
) that affected Crystal Reports from Business Objects. The technical bulletin offered the following warning:
An attacker who successfully exploited the vulnerability could retrieve and delete files through the Crystal Reports and Crystal Enterprise Web viewers on an affected system. The number of files that are impacted by this vulnerability would depend on the security context of the affected component that is used by the Crystal Web viewer.
Because the ASP.NET worker process runs by default as the lower privilege ASPNET account, and is not an administrator account (such as SYSTEM), the damage is limited to reading files in the file system, not deleting them. This was a change made to ASP.NET before its initial release in February 2003. Sure, it's still a bad bug: an attacker could read your BOOT.INI file, but at least they can't delete it. The bug is still bad because the attacker could also read your C:\WINDOWS\repair\sam file or, on Unix or Linux your /etc/passwd file (this bug affects all platforms that Crystal Reports runs on, including AIX, Solaris, and Linux—did you apply the patch?). Now, the bad guy could attempt offline password-cracking attacks.
If your code must operate with high privileges, remove any privileges not explicitly required by the application. For example, I'm working on a tool that requires a "dangerous" Windows privilege—the backup privilege. It's scary because any process running under an account with this privilege can read any file in the file system, regardless of the access control list (ACL) on the file. That's why it's called the backup privilege—you don't want a backup application to backup only certain files and not others because of an ACL conflict. There are two ways to solve this issue: I can run the service as SYSTEM, which has the privilege, or I can run the service under a specific account that only has this privilege. The problem with SYSTEM is that it has the backup privilege, but it also has the restore privilege, debug privilege, and the "act as part of operating system" privilege, and it's an administrative account, too. I think you can guess what I chose.
You should never run services as SYSTEM, or daemons as root, or user accounts with administrative rights unless you have exhausted all other possibilities. A defect in the code could lead to catastrophic failure. Set the default account to a lower privilege and if a corner-case scenario does not work, then let your administrator know which scenarios fail and allow her to make the change, if she feels the benefit outweighs the risk.
When people think of attack surface reduction, they often think of security design, which is good, but developers, not just designers and architects, can also help drive the process by analyzing anonymous code paths.Windows XP Service Pack 2: Information for Developers and Brian Johnson
Last year, just before the 2003 Professional Developers Conference, a group of us at Microsoft met to talk about how we were going to inform developers of the changes Windows XP Service Pack 2 would bring. These changes were first enumerated in a paper by John Montgomery, and Jason Garms spoke at the 2003 PDC about the upcoming changes so that developers would know what to do to make sure their applications worked with the service pack on release.
In the time since the 2003 PDC, Microsoft has created an SP2 product information site and made the SP2 Beta release generally available so that developers and IT professionals had the information they needed to test their applications.
Now that Windows XP Service Pack 2 has been officially released, developers should learn about changes in the operating system that may affect the applications they are currently building. The updates that are included in Service Pack 2 can be divided into four categories: networking, memory, e-mail and messaging, and Web development.
Networking The most important change in networking is that the Windows firewall is now turned on by default. This can have consequences for developers with applications that communicate over the network. In addition, all ports are now closed unless they are in use, access controls have been placed on DCOM, and the Remote Procedure Call.SubSystem (RPCSS) is now run with a reduced set of privileges.
Memory Buffer In the time since Windows XP was first introduced, Microsoft has developed a number of ways to help mitigate the potential damage done caused by buffer overrun attacks, one of the most common vectors of attack against software. Many of the core components in Windows have been recompiled with the /GS switch and other compiler technologies to help protect against such attacks. This recompilation is one of the reasons SP2 is such a significant update. In addition, Microsoft has worked with compiler vendors on Data Execution Prevention technology which will help prevent malicious code from running by enforcing a separation between areas of memory where applications are allowed to execute and areas that only hold data. This will help protect against a whole class of attacks on machines equipped with processors that support this feature.
E-Mail and Instant Messaging The default settings for Microsoft Outlook® Express and for Windows Messenger now provide attachment controls which are designed to act as a speed bump against attachments that carry a malicious payload. Microsoft has also created new APIs to assist in helping users and administrators make better trust decisions about attachments.
Web Development An important update offered in SP2 for Web developers is the inclusion of a pop-up manager, designed to reduce the number of pop-up windows that occur when one is browsing the Web. With SP2, a user usually must confirm that he wants a pop-up window to show before the browser will open the window. The pop-up manager also protects against running untrusted ActiveX controls. Developers need to be aware of how that mechanism works so that they can either guide their users through the confirmation process, or they can redesign their Web applications so that this restriction doesn't break the applications. In addition, the security in the Local Machine zone has been enhanced to help protect against malicious script and harmful Web downloads.
Microsoft is updating the tools delivered to developers with SP2 in mind. The Microsoft Platform SDK has been updated to support SP2, so you'll want to consider updating your PSDK installation to better handle changes in the operating system. In addition, new Service Packs for the .NET Framework 1.0 and 1.1 have been released to help developers take advantage of security enhancements and Execution Protection on those processors that support it. Looking forward, the .NET Framework 2.0 and Visual Studio®
2005 are being designed with a major focus on the security technologies offered in SP2.Microsoft has created a number of resource portals on the Web where you can find related articles and training on SP2. First, be sure to check out the Windows XP Service Pack 2
site on the MSDN Security Developer Center. There you will find links to the SP2 download, a link to the debug (checked) build of the service pack for developers, and links to articles, training, and webcasts designed to help make you successful with this new technology.
You'll also want to visit the following sites for additional information: Windows XP Service Pack 2
on TechNet and Support for Windows XP Service Pack 2 for Developers
Action: Reduce the privileges under which your code must execute.
Anonymous Code Paths
One part of the threat modeling process involves building data flow diagrams (DFDs), or using a similar technique, such as Unified Modeling Language (UML) Interaction diagrams, to identify the entry points into the application. It is these entry points that can be accessed by attackers. As a developer, you first need to make sure that all the entry points into your code are factored into the DFD. Next, you should look at each entry point to determine what privilege is required to access that entry point. Then trace through the DFD, look for all the potential data flows, data stores, and processes that the code touches, or, more to the point, code that an attacker can touch. Let's assume your code has only two network-facing entry points; one is anonymous and the other can only be accessed by administrators, because your code authenticates the user before they can continue execution. Now sit back and think for a moment: where's the bad guy going to go? He's going to attack the code along the anonymous data path (also called a threat path) simply because he can. He's not going to exercise the administrative code path because, if he can, then he's already an administrator and your problems are only just starting.
Action: As you review the DFD, look for anonymous threat paths. It may be prudent to raise the authorization bar on these paths using some of the methods outlined.
Watch Out for Those Little Protocols
Microsoft issued a security bulletin in early 2004 that affected Windows 2000, Windows XP, and Windows Server 2003. One of the defects fixed was in the Private Communications Transport (PCT) protocol, which is part of the Microsoft Secure Sockets Layer (SSL) library. PCT was used in the past when U.S. federal cryptographic export restrictions existed. Today, there are no such restrictions, so PCT is not often used anymore. That's why in Windows Server 2003, PCT was disabled altogether, and because this bug was in PCT, Windows Server 2003 was unaffected by default, even though the defect was in the code. Windows 2000, however, was affected because PCT is enabled by default on SSL-enabled Windows 2000 Web servers, so for them this fix is critical.
Another protocol to watch out for is User Datagram Protocol (UDP). It's interesting that many applications that use TCP also listen for UDP traffic when they don't need to. If your application uses only TCP, then don't listen for UDP traffic. Remember Slammer? Slammer was an effective worm because the payload fit in one UDP packet. Because there is no three-way handshake like there is in TCP, the worm could travel very rapidly indeed. See Analysis of the Sapphire Worm
for an interesting analysis of the worm's impact.
It's also really important you reduce your attack surface as early as possible in the design process.
Action: Apply the 80/20 rule to every network protocol you consume.
Reduce Attack Surface Early
Waiting to reduce your attack surface late in product development is often very difficult because changing functionality late in the game guarantees you'll cause regression errors. Other features probably depend on the functionality to work in a specific way, and you just changed it!
We had an issue like this when we reduced the attack surface of Microsoft Internet Explorer in Windows Server 2003; Windows Update stopped working, so we had to make some small changes in order to make it work.
When designing your application, you should have a section in the design outlining what the attack surface will look like. You should identify items like the following:
- The networking protocols you enabled by default.
- The endpoints that should support authentication and authorization. Focus on other anonymous endpoints.
- The off-by-default features. Look for code that auto-starts or will execute when accessed, such as services, daemons, ISAPI filters and applications, SOAP services, and Web roots.
- Reusable components (ActiveX® controls, COM objects, and .NET Framework assemblies, especially those marked with the AllowParticallyTrustedCallersAttribute).
- Process identities for all the code you run.
- User accounts installed.
When developers know early what the attack surface looks like, they can design and code accordingly from the start, rather than waiting for a big, nasty surprise at the end. Waiting too long causes huge code churn and bad feelings as designs must change to accommodate the disruption.
Measuring Attack Surface
As each week in the development cycle passes by, you should measure the attack surface of your product. Start with a baseline, and then each week count all the items identified in the previous section using various scanning tools. In some cases, you may need to write your own tools if you have entry points specific to your application. If the attack surface count goes up, determine why it went up, and see if you can drive it back down. When engineers know you are measuring the attack surface, they will try not to stand out by increasing the attack surface in the first place. See Figure 1 for an example.
Figure 1 Comparing Attack Surface Against a Baseline
||Baseline + 1 month
|3 x TCP ports
||2 x TCP ports
||Good; one fewer port to worry about.
|1 x UDP port
||2 x UDP port
||Which functionality opened the new UDP port? Why is it open by default? Is it authenticated? Is it restricted to a subnet?
|2 x Services (both SYSTEM)
||3 x Services (2 x SYSTEM, 1 x LocalService)
||Why is another service running by default? Why are any running as SYSTEM?
|3 x ActiveX controls
||4 x ActiveX controls
||Why is the new control installed? Is it safe for scripting?
|No additional user accounts
||1 x application account
||Turns out this is a member of the administrators group too! Why? What's the password?
Action: Define your minimal attack surface early in development, and measure it during development.
Big Attack Surface = Big Security Work
After all of this, if you decide that you must ship an application with a large attack surface, obviously, that's bad. Not only does it mean your customers may be attacked by default, but it means you have a lot of code to review. I like to look at it this way: a large attack surface means you have a great deal of faith in your code quality. The only way you can trust the code is by having very extensive code reviews and by making sure the code is defensive and conservative. Imagine two similar products, one from you and the other from a competitor. Your competitor's product does not run by default, runs with least privilege when it does run, and only opens one TCP socket, which is restricted to the local subnet by default. Your product runs by default as SYSTEM, opens one UDP and three TCP sockets, and they are all unauthenticated and Internet facing. Enter an attacker—which system is he going to attack? I'll give you a hint: yours! If there is a flaw in your code, he can probably compromise the server on which your code runs. Better yet, he can attack your other customers too, because they all have the functionality running by default.
Finally, let users and admins know what you did. Document the features affected by the reduced attack surface and explain how customers can tweak the system if they run into problems because of these settings. Be conservative in your recommendations and make sure your customers know the implications of enabling a port or feature. If your application relies on a firewall and users want to access some functionality using a specific port, just tell them which port to open; by all means don't tell them to turn the firewall off!
Action: If you have a large attack surface, you must spend more time making sure the code is excellent quality, conservative, and defensive. A large attack surface says: "Hackers, come get me!"
Jon Pincus (Microsoft Research), Jeanette Wing (Carnegie Mellon University), and I authored an academic paper entitled "Measuring Relative Attack Surfaces" that was presented in Proceedings of Workshop on Advanced Developments in Software and Systems Security
. Also, a student of Wing's, Pratyusa Manadhata, has coauthored a paper with her, "Measuring A System's Attack Surface." Both are available at http://www-2.cs.cmu.edu/~wing
A group of security consultants from Ernst and Young LLP wrote a paper entitled, "Using Attack Surface Area and Relative Attack Surface Quotient to Identify Attackability of Windows Server 2003
" about the use of the relative attack surface analysis technique.
Michael Howard is a senior program manager, a founding member of the Secure Windows Initiative group at Microsoft, and a coauthor of Writing Secure Code (Microsoft Press, 2002). He focuses on designing, building, testing, and deploying applications that are designed to withstand attack, yet are still useful to millions of nontechnical users.