New Security Features in Visual Studio 2005
Summary: Visual Studio 2005 makes it easier for developers to write secure applications. Write unmanaged code that's safe, or get IDE tools that help you to build and deploy managed applications that take advantage of Code Access Security. (11 printed pages)
Developers want to build safe applications, but most developers don't want to spend an inordinate amount of time learning about securing their applications. They would rather write the code and the algorithms that solve the problem and ship the product, without having to worry about security. Currently, however, we can't build fire and forget applications. We need to understand the security implications of the decisions that we make. With that in mind, the tools that we use to build and ship applications can make it much easier to ship secure applications. In this paper I'll review some of the features of Visual Studio 2005 that can help you build secure and robust applications. Most of the tools and enhancements in Visual Studio 2005 require very little extra work and can have a tremendous impact on the overall security of your applications.
Visual C++ is the only Visual Studio compiler that gives you the option of directly targeting a processor (i.e., create unmanaged, native exes and dlls).
We'll discuss security enhancements for native code in this section with the caveat that this material applies to Visual C++ unless otherwise specified.
The vast majority of security problems that are found in native code fall into the category of buffer overruns. Buffer overruns occur when data exceeding the size of a buffer is pushed into a part of memory from which code can be executed. This becomes a problem when a clever attacker figures out exactly how much he needs to overrun the buffer in order to place an instruction into a portion of memory from which he can hijack the execution of the program.
With that rather simplified definition of a buffer overrun in mind, four features of Visual Studio 2005 are described that are designed to help you spot potential vulnerabilities in your code, and to help prevent an attacker from capitalizing on vulnerability, should one slip through.
Code Analysis /analyze
Code Analysis is a feature of Visual Studio 2005 Team Edition for Software Developers. This feature was derived from a utility first used internally at Microsoft called PREfast. It was shipped publicly with the Microsoft Device Driver Kit (DDK). The code analysis feature works by analyzing the C and C++ source code, stepping through all possible execution paths in each function and simulating execution to evaluate each path for problems. Code analysis doesn't execute code and cannot find all possible errors, but it can find errors that the compiler may ignore. Code analysis finds problems in areas such as casts and data types, performance, security, expressions, loops, memory allocation, format strings, return values, and exception handling.
With Code Analysis enabled in Visual Studio 2005 Enterprise Edition, detected errors are shown in the Error List window. You can enable code analysis using the /analyze option, or by setting the Enable code analysis for C/C++ option to Yes(/analyze) in the General section of the Code Analysis Node in the Property Pages dialog box, as shown in Figure 1.
Figure 1. The Security Rules available through Code Analysis
Application Verifier (AppVerifier) originally shipped as part of the Application Compatibility Toolkit. AppVerifier is a set of run-time analysis tests that helps detect execution errors in programs. The errors detected by Application Verifier deal mostly with application compatibility, stability, and security issues and fall into one of three different categories: handle verification, locks verification, and heap verification. The settings for AppVerifier are found in the Application Verifier node in the Property Pages dialog box.
To start Application Verifier, on the Debug menu, click Start with Application Verifier. Application Verifier uses stops to provide information when errors are found in the different verification layers. Developers can set Application Verifier to perform specific actions when a stop appears. These actions include breaking on and logging errors. Figure 2 shows the Application Verifier settings in the Property Pages dialog box.
Figure 2. Stop options with Application Verifier
Buffer Security Check /GS
The Visual C++ Buffer Security Check compiler option (/GS) is designed to help prevent malicious code from taking advantage of buffer overruns in applications. Buffer overruns account for a large number of vulnerabilities in code. The /GS option works by setting an encrypted value (sometimes called a canary) at the end of a buffer. This value is checked during code execution and if has changed, program execution is halted and a security exception is raised.
The /GS option doesn't prevent the buffer overrun, but it does protect against the possible hijacking of the code by stopping program execution.
The Safe CRT Libraries
The Safe CRT Libraries are an overhaul of the standard C and C++ libraries. They are designed to improve security of applications compiled with Visual C++ by adding appropriate buffer checks to functions known to be vulnerable to attack and to depreciate vulnerable runtime function.
These changes affect all of the major programming libraries including the C Runtime Library (CRT), the Standard C++ Library (SCL), the Microsoft Foundation Classes (MFC), and the Active Template Library (ATL). As part of this overhaul, MFC and ATL were rebuilt to use the Safe C Library functions, and so recompiling MFC and ATL apps with Visual C++ 2005 will provide some of the benefits of the Safe CRT libraries automatically.
For information about the Safe CRT libraries, see the MSDN Magazine article, Repel Attacks on Your Code with the Visual Studio 2005 Safe C and C++ Libraries by Martyn Lovell (Microsoft Visual C++ Development Lead).
Managed code brings a slightly different set of security concerns, but because of the way that memory is handled in the common language runtime (CLR), traditional buffer overruns are less of a problem. In this section, I'll review some of the Visual Studio 2005 security features that are most important to developers who are writing managed applications.
Developers have used the stand-alone FxCop tool for years to check assemblies for conformance with the .NET Framework Design Guidelines. This tool is now built into Visual Studio 2005.
FxCop performs its analysis by parsing the MSIL instruction stream and analyzing the call graph for violations to rules specified by the user, usually in accordance with the .NET Framework Design Guidelines. These include security rules, library design rules, and rules on globalization, interoperability, maintainability, naming, performance, reliability, usage, and others.
You can access the FxCop functionality in Visual Studio 2005 through the Code Analysis tab on the Project Properties page for your managed application. Figure 3 shows some of the security rules you can review as part of your analysis.
Figure 3. Accessing the Code Analysis rules in Visual Studio 2005.
You enable Code Analysis by checking the Enable Code Analysis box on the Code Analysis Properties Page for your managed project. Doing so will generate additional warnings in the Visual Studio 2005 Error List window. You can reduce the number of items in the list by choosing to analyze only the rule sets that you're interested in; for example, Security Rules and Reliability Rules.
Code Access Security/Least Privilege
.NET Framework applications run under a security model called Code Access Security. This is an evidence-based model, where security privilege is granted based on factors such as the location of the assembly and the assembly's signature. These factors are compared to a policy set at the user-, machine-, or domain level. The policies associated with these different factors allow applications to run with very specific permissions granted. This concept is described as partial trust.
One of the difficulties in deploying partial-trust applications is in testing the applications as they're being developed. The developer would normally have full permission to run an application she's building, but to see how that application would behave on an intranet or the Internet, she would need to move it to those locations to test the application under those conditions. Visual Studio 2005 helps in this regard by providing a number of tools and features that developers can use to test and debug their applications from the IDE to ensure that they will operate properly under the trust level granted to them by policy when they are deployed.
ClickOnce is a technology built into Visual Studio 2005 that makes it easy for developers to build applications to be deployed to users running under limited permission accounts. These applications can run locally or from an intranet share or an http link on a Web page. Applications run from network locations are cached and run locally, but do so with the permissions granted only to the location where the application actually resides. When the developer deploys a new version of an application to a network location, that location is checked first when the end user launches the application and the cache is updated.
Visual Studio 2005 makes it possible for developers to test the execution of these partial-trust applications from within the IDE. This can save much time and effort around building and deploying applications with CAS.
Debug in Zone
To take advantage of ClickOnce, it's important that developers can easily test their applications with the same set of permissions that will be granted to the application when it's deployed. The Debug in Zone feature lets developers specify the amount of trust that the application will need as they design and debug the application, making it possible to test the application as deployed to a network location with varying levels of trust. This functionality is accessed through the Security tab in the Project Properties pages for a managed application.
To use this feature, open the Security tab for the project and specify that this is a partial-trust application. From here you can choose the zone under which you want to install your application and you can specify which permissions your application will require when deployed. You can see these settings in Figure 4.
Figure 4. Specify the security permissions for your application on the project's Security tab.
Improved Security Exceptions during Debugging
Once you've set your zone, running the application will generate security exceptions for that zone as the application is run. The new security exception dialog shown in Figure 5 gives you an idea of what you can expect when you run into security exceptions as you debug your applications.
Figure 5. Security exceptions in Visual Studio 2005
The Security Exception window does much more than just provide you with a notification. It lists advice and steps you can take to change the application to make your application work under a partial-trust scenario. For example, the FileIOPermission is not allowed in the zone under which the program in Figure 4 was run. One of the suggestions for rectifying this problem is to use isolated storage for the application.
IntelliSense in Zone (Visual Basic feature)
IntelliSense in the Zone is a security feature specific to Visual Basic. Security in the Zone constrains the options offered by IntelliSense to only those APIs that are allowed for a specific zone. Functions not available in the current zone are grayed out. This helps developers building partial-trust applications to select only the APIs that are known to be permissible for a particular zone.
PermCalc is a stand-alone application that's used by .NET developers to analyze the permissions needed to run a managed application successfully. This functionality has now been added to Visual Studio 2005 and is just a click away on the Security tab in the Project Properties window for a managed application.
To use PermCalc in the IDE, set the installation zone for your application and then click the Calculate Permissions button. If your application requires more permission than is available for the zone, you'll see the word "Include" in the Settings column of the permissions table on the page as shown in Figure 6. These items will be marked with a caution symbol to indicate that the permission required is not available by default in the selected zone. If the PermCalc utility determines that the application requires full trust to run correctly, you'll see a message box informing you of that fact.
Figure 6. Calculate Permissions determines which permissions will be required by an application in order to run correctly.
There are a number of Visual Studio 2005 security enhancements that are useful for in both native and managed projects. Next we'll look at developing with least privilege and testing as is applies to security.
Develop and debug as least privilege
One of the ways that computer users can prevent malware from affecting their systems is to reduce the level of privilege under which they run. A piece of malware that's run by a user with administrative privileges has access to every part of the machine. From a general security perspective, running as administrator should be avoided.
In addition, developers logged in as administrators don't see the problems that users with less privilege see when they run the application. For example, an application that writes to the Program Files or System folders will work seamlessly for a user running with administrative privileges. Write access to these folders is limited for accounts running as User, so attempts by the application to save data in these places will fail.
With past versions of Visual Studio, it was difficult to build and debug applications using accounts with reduced privileges because Visual Studio itself runs best under high-privilege accounts. With Visual Studio 2005, this situation has changed. Visual Studio 2005 runs cleanly under a User account and you can develop and debug applications this way as easily as you could as an Administrator or Debugger User previously.
Keep in mind that even under Visual Studio 2005, you might run into problems with add-ins that are designed to work with higher privilege accounts. As you run into such situations, let your add-in vendors know that their add-in is demanding more privilege than is probably needed. In most cases redirecting storage or registry requests to the appropriate place will allow the add-in to run correctly.
Testing for security issues is an extremely important part of building your application for use in a connected environment. Visual Studio 2005 Team System features a number of testing tools that will help you produce more secure applications.
One of the things that unit tests are used for is to ensure that the return value of a method is what is expected, given the values passed to the method. When processing user data, it's important to ensure that that data is what you expect it to be. This includes the type and the length of the data, two factors that should be verified before you process that data. You can use unit tests to send random data to a function and ensure that the application is handling the data the way it should be and that the application is behaving appropriately.
In addition, code coverage can be enabled in your unit tests. Code coverage helps ensure that code within the application is tested. This helps prevent little used code, such as an exception handler to be missed. Code that isn't part of the normal flow in an application can still be vulnerable to attack. There have been numerous cases of attackers taking advantage of code designed to run when normal flow is interrupted.
Visual Studio 2005 features a number of testing tools that allow you to create unit tests. You can create a unit test by hand in Visual C++, Visual C#, or Visual Basic from the Add New Test dialog box shown in Figure 7.
Figure 7. Creating a new unit test from the Add New Test dialog box in Visual Studio 2005
In addition to creating unit tests by hand, you can create tests using the Unit Test Wizard. This can help you get to know how these types of tests work and will give you a starting point for your own tests.
Stress (Load) testing
Load testing is important because it helps you debug scenarios such as possible denial of service attacks that might be launched against your Web applications. The Load Test template in the Add New Test dialog box invokes the New Load Test Wizard shown in Figure 8. In addition to performing load testing for what you might expect your application to experience, you can use this tool to test abnormal scenarios. Do this by sending a huge number of requests against your application to see how it holds up to the load. By observing your application closely, you can begin to recognize an attack and you can plan a response for one of these types of attacks if necessary.
Figure 8. Preparing a load test in Visual Studio 2005
This paper provides a brief overview of some of the security features that make Visual Studio 2005 such an important new tool for developers. Whether you're building a small utility or a huge, mission-critical system, the safety of your customer's machines and the security of the applications you build should be a top priority. With the new tools built into Visual Studio 2005, you can build, test, and deploy secure application more easily than ever.
Brian Johnson is a Program Manager at MSDN. He's responsible for the content on the Visual Studio, Visual C++, Security, and the .NET Framework Developer Centers on MSDN.