Laying the Foundation for the Microsoft Security Development Lifecycle: Implementing the Principles

Published: April 9, 2008

By Jeremy Dallman, Security Program Manager, Microsoft Security Engineering & Communications

See other Security Tip of the Month columns

One of the phrases frequently used in strategy planning at Microsoft is "crawl, walk, run.” This phrase is used to differentiate initial activities that get us quickly moving toward larger goals from other activities that may require longer preparation or planning. As you move toward implementing the Microsoft Security Development Lifecycle (SDL) in your development lifecycle, this "crawl" phase is very important. Usually some person in an organization picks up on the principles of SDL and is ready to roll them out immediately. However, that initiative is often faced with competing interests that complicate immediate and full adoption: for example, the team is midstream in development, short on budget, or management wants to see clear evidence before investing in the changes to support full SDL adoption.

Historically, we have focused on how to roll out a full lifecycle solution. This paper attempts to define what it means to start “crawling” toward SDL. It is very important to note that what is described in this article is not SDL. It matches some of the tools and principles, but does not encompass the holistic application security solution provided by SDL.

To start crawling toward SDL, you need to execute on some of the core principles. They obviously need to be low-cost and effective. These principles can be summarized into three areas of focus:

  1. Detailed awareness of your architecture and its attack surface.

  2. Tools that will perform security analysis on your application.

  3. Results that show how the analysis resulted in improved security.

The good news is that you can attain these components with tools that are already available. The one consistent minimum requirement is that your code compiles/builds within Microsoft Visual Studio 2005 SP1. Using this version is important because significant defenses discussed below are only available in Visual Studio 2005 SP1. Let’s look at some of the tools that you can use to get “crawling” toward SDL today.

Detailed awareness of your architecture and its attack surface

Threat modeling is very important for uncovering vulnerabilities in your architecture. Even if you are past the design phase, assign someone to do a retrospective model (perhaps as part of a pre-release review). This will likely give you a better understanding of your overall architecture and uncover potential security issues in places you may have inadvertently overlooked.

Tools that will perform security analysis on your application

Tooling is one of the most often discussed topics around SDL, so we’ll spend some time providing more detail in this area. This section will break down the impact of tooling across three key disciplines of your team: development, testing, and operations. These roles are generic enough that you should be able to translate the information effectively into your individual organizational structure.

You should strengthen your compiler defenses. These will differ depending on whether you are writing native or managed code.

For C and C++ code:
Strengthen your compiler defenses

  • Use the latest compiler and linker because important defenses are added by the tools.

  • If using Visual C++, use Visual Studio 2005 SP1 or later.

  • Compile with appropriate compiler flags.

  • Compile clean at the highest possible warning level.

  • Compile with /GS to detect stack-based buffer overruns.

  • Link with appropriate linker flags: /NXCompat to get NX defenses, /DynamicBase to get ASLR, and /SafeSEH to get exception handler protections.

Do not use banned APIs in new code

  • Use #include “banned.h” header file to find banned C/C++ functions in your code quickly. This header file is included in the companion disk in the Security Development Lifecycle book.

  • Compile regularly with /W4 and fix all C4996 (banned C Runtime function) warnings.

For All Languages:
Strengthen your compiler defenses

  • Use the latest compiler, linker, and libraries because defenses are added by the tools and code.

    • If using C#, use C# v2.0 or later; if using Visual Basic .NET, use 8.0 or later.

  • Use Microsoft .NET Framework 2.0 or later.

  • Do not use weak crypto in new code.

    • Use only AES, RSA, and SHA-256 (or better).

  • Prevent XSS vulnerabilities by using filtering and escaping libraries around all Web output.

  • Secure your SQL script by only using prepared SQL statements—no string concatenation or string replacement.

Run these tools habitually

  • PREfast (in Visual Studio 2005, use the /analyze compiler option): This static analysis tool identifies defects in C/C++ programs and enables you to perform quick desktop error detection on small code bases.

  • FxCop: This application analyzes managed code assemblies (code that targets the .NET Framework common language runtime) and reports information about the assemblies.

  • Application Verifier (AppVerif): This tool detects and helps debug memory corruptions, critical security vulnerabilities, and limited user account privilege issues.

James Whittaker has covered testing in the SDL on the SDL blog in the past. Please refer to that information for deeper context. In a “crawl” scenario, simplicity and maximized value of output are the primary goals. Fuzz testing provides the highest value with minimal work in this area. Because of the nature of fuzzing, this is likely something you will need to invest some time creating. For more guidance, refer to Scott Lambert’s article, “Fuzz Testing at Microsoft and the Triage Process.” This paper provides some good guidance on how to think through what type(s) of fuzzing to exercise against your application.

If you choose to expand beyond fuzz testing, I would point you back to Whitaker’s article on the broader topic of Testing in SDL. You may come to the conclusion that expanded security testing may come later in your “walk” or “run” phases, but it is important that you take some time to think through testing even while “crawling” to ensure broad test coverage for your application. The three-pronged approach to security testing in his article reflects our approach at Microsoft. You should use these three approaches to ensure that your own fuzz testing is comprehensive.

  1. Attacks against the application’s environment.

  2. Direct attacks against the application itself.

  3. Indirect attacks against the application’s functionality.

Results that show how the analysis resulted in improved security

Operations - Response planning
Protecting your customers is the reason for focusing energy on application security. If there are security issues in your code that you don’t uncover, someone else will. It is absolutely critical that you are prepared to respond rapidly and protect your customers. It is equally important that you construct your response plan to serve as a front-line barometer for detecting the resilience of your security design and what pieces of your applications security should be proactively bolstered to address externally reported vulnerabilities.

The knowledge that you harvest from these security incidents (typically through root cause analysis) is the primary way to improve your code and security tooling for the future. Do everything you can to learn lessons from the vulnerabilities others find. If you don’t have a response plan in place, you need to establish one as soon as possible. If you don’t know where to start, take a look at the Microsoft Security Response Center and fit to your scale or pick up the Security Development Lifecycle book and dig into the four-step process outlined.

The four steps of the Emergency Response Process are:

  1. Watch

  2. Alert and Mobilize

  3. Assess and Stabilize

  4. Resolve

Bugs, Bugs, Bugs
Gathering evidence that clearly shows that your work has improved the security of your application is always a challenge. Trying to keep it lightweight adds to that challenge. The most effective way to create traceable and practical evidence without a lot of overhead is detailed management of security issues in your bug database. The key here is that you can configure your bug database and query it in a variety of ways to pull out this data. From the time you set out to implement this plan, be strict in tracking every discovery from threat modeling, the mitigations to those threats, and every bug you expose in tool analysis. This library of bugs will give you an easy way to go back and gather evidence that shows the quantity of issues you discovered, the mitigations you used, and the impact the changes had on your application.

This paper is meant to provide an effective, yet scaled-back entry into the principles of SDL to get moving toward improved security assurance. Following these steps will prove effective in establishing a baseline architectural understanding of your application security, identifying critical weaknesses, and providing enough evidence to support the decision to “run” forward into full SDL adoption.