The Microsoft SDL and the CWE/SANS Top 25 Bryan Sullivan, Security Program Manager, Microsoft Corp. Michael Howard, Principal Security Program Manager, Microsoft Corp. Introduction The purpose of this document is to present an overview of how the Microsoft SDL maps to the CWE/SANS list of the Top 25 Most Dangerous Programming Errors. This document will assume that you’re familiar with the vulnerabilities described in the SANS/CWE list. If not, please follow the hyperlinks on the CWE items that will take you to the appropriate page on the MITRE web site. The list is organized into three categories: Insecure Interaction Between Components Risky Resource Management Porous Defenses. Insecure Interaction Between Components CWE-20: Improper Input Validation As Adam Shostack has blogged so often, threat modeling is critical to the SDL. The SDL requires development teams to threat model their applications, and the SDL Threat Modeling Tool is one of the most widely used tools for this activity. The tool automatically adds potential input tampering threats to any Data Flow Diagram (DFD) process elements added to the model. Modelers are prompted to ensure that all inputs to the process across all execution paths are verified for correctness. Allow-list validation techniques are suggested as appropriate mitigations. The SDL also includes specific guidance around using input validation to prevent cross-site scripting (XSS), the most prevalent web application vulnerability. Developers are required to validate or sanitize all incoming data against XSS attacks by blocking or removing potentially malicious script input. Details on how to accomplish this can be found in the September 2008 MSDN magazine article “SDL Embraces the Web”. As a defense in depth measure, the SDL also requires use of the ValidateRequest feature of ASP.NET, which automatically blocks some forms of script input. Finally, we have a security training class dedicated to Web-based vulnerabilities. CWE-116: Improper Encoding or Escaping of Output The SDL requires output encoding of data written to web pages (to prevent XSS vulnerabilities) and escaping of input passed to SQL commands (to prevent SQL injection). HTML output encoding is actually much trickier to perform correctly than many developers believe. To make this process easier, the SDL requires developers to use the CISG AntiXSS library. 1 SQL command input escaping is required implicitly by the SDL requirement to always use stored procedures for all database access. The database stored procedure logic will automatically escape input to a safe format and prevent SQL injection vulnerabilities. This subject is covered in our Security Basics class, as well as many other secure coding classes. CWE-89: Failure to Preserve SQL Query Structure (aka SQL Injection) SQL injection vulnerabilities are thoroughly covered by the SDL. Besides the requirement to always use stored procedures for all database access mentioned earlier, there are two additional requirements. The first is to avoid the use of the SQL EXECUTE/EXEC command in your stored procedures (or more precisely, to only use EXECUTE to call other stored procedures, never to execute arbitrary SQL commands). Without this requirement, you could accidentally undo the security benefits of using stored procedures by coding vulnerable T-SQL code directly into the stored procedure. The second requirement is a defense-in-depth feature. All direct table and view privileges for the interactive user for the database must be revoked, and only execute permissions for the necessary stored procedures granted. This requirement dramatically lowers the damage that any potential attack could cause: attackers will be limited to only calling those functions that the application is already designed to access, and they will not be able to (for example) iterate through the sys.objects table or call the xp_cmdshell procedure. The subject of SQL injection is covered in our Security Basics class, as well as in the Web-based vulnerabilities class. CWE-79: Failure to Preserve Web Page Structure (aka Cross-Site Scripting) XSS vulnerabilities are also thoroughly covered by the SDL. As mentioned earlier, the SDL has implementation requirements around validating and sanitizing input (removal of malicious script input, also ValidateRequest) and output encoding (AntiXSS library). As an additional verification step, the SDL also requires the use of static analysis to detect possible XSS vulnerabilities. Specifically, it requires the use of the CISG Code Analysis Tool for .NET (aka CAT.NET) for managed code projects. Internal Microsoft teams have been using this tool with great success for a while now, and we’re very happy that CISG has recently made a free Community Technology Preview of it available to the public. This subject is covered in our Security Basics class, as well as in the Web-based vulnerabilities class. CWE-78: Failure to Preserve OS Command Structure (aka OS Command Injection) The SDL-mandated CAT.NET tool is also required to detect potential SQL injection problems, openredirect phishing, XPath and LDAP injection, and some types of command injection vulnerabilities. Any dataflow source that ends at a System.Diagnostics.Process or ProcessStartInfo sink without passing through an appropriate validation function will flag as a potential command injection vulnerability. The SDL also recommends that applications be granted minimal privileges and apply appropriate ACLs – for 2 instance, denying access to the file system, or allowing only read-only access to the registry – so that developers can reduce the damage that any successful command injection attack would cause. This subject is covered briefly in our Security Basics class and at length in our Secure Code Review and Secure Design classes. CWE-319: Cleartext Transmission of Sensitive Information Our threat modeling process would uncover these design vulnerabilities: they are considered Information Disclosure vulnerabilities in the STRIDE taxonomy. The recently released SDL Threat Modeling Tool will prompt the modeler to answer the following questions for all data flow elements added to the diagram: 1. If there is a channel and/or message encryption system for the data flow as a whole, is it strong, and in accordance with the Crypto Board and SDL requirements? 2. If not, or if there is not a confidentiality system, what prevents information disclosure? The tool also offers the suggestion to encrypt the data flow if it crosses a network, or to use appropriate ACLs if it’s on a single system. (The definition of “strong” channel encryption per the SDL standards will be discussed later in this post under the topic CWE-327, Use of a Broken or Risky Cryptographic Algorithm.) Finally, this topic is covered at length the Security Basics class, Secure Design Class and Threat Modeling class. CWE-352: Cross-Site Request Forgery (aka CSRF) Cross-site request forgery vulnerabilities are covered by the SDL requirement to use the ViewStateUserKey feature of ASP.NET. Setting the ViewStateUserKey property creates a secret “canary” value shared between the client (stored in the page view state) and the server (calculated or stored as the developer desires). Any request missing a valid ViewStateUserKey value is assumed to be a malicious forgery and the request is denied. Note that this only mitigates some forms of POST-based CSRF attacks. HTTP GET requests have no request body, and therefore no view state, and therefore cannot use view state-based defense mechanisms. CSRF (and related) vulnerabilities are discussed in depth in the Web Security class. CWE-362: Race Condition In reviewing the CWE/SANS list thus far, we have had requirements in place to mitigate all the vulnerabilities discussed. In some cases we’ve had many overlapping requirements to provide defensein-depth. But we do not have any specific SDL requirements to detect possible race conditions. The main reason for this is that race conditions are notoriously difficult to detect and reproduce. Until someone develops an automatic analysis tool to accurately detect potential race conditions, our only way to find these issues is through manual code review. While we don’t consider code review a complete solution, 3 we note that we’ve only issued three bulletins concerning race condition vulnerabilities in the last ten years. Race conditions and Time of Check/Time of Use (TOCTOU) vulnerabilities are discussed in the Secure Design class. CWE-209: Error Message Information Leak The SDL recommends that error messages should present just enough information to provide the user a clear understanding of what an appropriate action to take would be, but not any information that would help an attacker to compromise the system. Further guidance to help a developer determine how much information is “just enough” can be found at http://msdn.microsoft.com/en-us/library/ms995351.aspx. In addition, CAT.NET (available in Visual Studio, and as a standalone tool) will detect when inappropriate exception information is presented to the user. Any internal stack traces or exception messages (determined by either the Exception.Message property or the Exception.ToString method) displayed to the user will be flagged as information disclosure vulnerabilities. This topic is explained in detail in the Security Basics class, primarily in the context of SQL injection vulnerabilities. Risky Resource Management CWE-119: Failure to Constrain Memory Operations within the Bounds of a Memory Buffer Beyond a doubt, buffer overflows are the most thoroughly covered vulnerabilities in the SDL. The most recent version of the SDL has at least nine requirements concerning overflows, and more if you consider the primary purpose of fuzz testing to be finding overflow vulnerabilities. Let’s take a quick look at each requirement: Use static analysis tools to find code with potential vulnerabilities. The main tool we use is PREfast – available externally as the /analyze option in Visual C++. Avoid banned APIs. Avoiding the API calls that can lead to overflows is the primary defense against overflow attacks. An easy way to find these APIs is to include Michael’s banned.h header file which will deprecate all unsafe functions. You can find banned.h here: http://download.microsoft.com/download/2/e/b/2ebac853-63b7-49b4-b66f9fd85f37c0f5/banned.h Use the /GS compiler option. /GS causes the compiler to insert stack cookie-checking code around function calls. If an attacker tries to smash the stack (either for fun or profit), the cookie value will be changed and the application will stop executing. A detailed analysis of this mitigation can be found at http://blogs.msdn.com/michael_howard/archive/2007/04/03/hardening-stack-based-bufferoverrun-detection-in-vc-2005-sp1.aspx. Link with the /NXCompat flag to enable Data Execution Prevention (DEP). DEP helps to prevent exploitation of overflow vulnerabilities by preventing data from being executed as code. See http://msdn.microsoft.com/en-us/library/ms235442(VS.80).aspx 4 Link with the /DynamicBase flag to enable Address Space Layout Randomization (ASLR). Another defense-in-depth mechanism that complements /GS and /NXCompat, ASLR randomizes the locations of function calls to make exploiting any existing overflow vulnerabilities more difficult. See http://blogs.msdn.com/michael_howard/archive/2006/05/26/address-space-layoutrandomization-in-windows-vista.aspx for more information. Link with the /SafeSEH flag to enable safe structured exception handling. SafeSEH compiles a table of valid exception handler addresses at link time and adds this table to the image. If an attacker tries to define his own exception handler in order to execute arbitrary code of his choosing, the application will fail the handler address table verification check and stop executing. Use the HeapSetInformation function with the HeapEnableTerminationOnCorruption flag. In the event of heap corruption (that might occur from a buffer overflow attack, for example), the application will shut down. You can find more information at http://blogs.msdn.com/michael_howard/archive/2008/02/18/faq-about-heapsetinformationin-windows-vista-and-heap-based-buffer-overruns.aspx. Run Application Verifier to detect heap-related buffer overruns and double-free errors through dynamic testing. Use –fstack-protector-all for Apple OS X applications (such as Mac Office). This is a stack cookie protection similar to /GS. (Don’t be so surprised! Microsoft makes OS X applications too and we want them to be just as secure as our Windows applications, and online services, and Xbox games, and hardware devices, etc…) Use library randomization for Apple OS X applications. The –WI, -pie compiler options provide a similar feature to ASLR for OS X. Use the GCC fortify source compiler option for Apple OS X. The GCC compiler option – D_FORTIFY_SOURCE=2 will automatically migrate some overflow-vulnerable API calls to their safe equivalents. In addition, the SDL also makes several recommendations around overflow defense: Automate banned API replacement. Visual C++ 2005 and later versions support the ability to automatically replace some overflow-vulnerable API calls with their safe equivalents. For example, calls to strcpy will be replaced with calls to strcpy_s. To use this feature, include this line in one of your header files: #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES (1) Encode long-lived pointers such as global function pointers or pointers to shared memory regions with the EncodePointer or EncodeSystemPointer function. This is a defense-in-depth measure designed to make exploitation of overflow vulnerabilities more difficult for the attacker. You can read more at http://blogs.msdn.com/michael_howard/archive/2006/01/30/520200.aspx. Avoid global exception handlers. Using catch-all global exception handlers may prevent the application from crashing, but it also gives attackers more opportunity to exploit vulnerabilities. The ASLR defense for example will be negated if you use exception handlers like these. The 5 PREfast Analysis Tool (included in Visual Studio with the /analyze compiler option) and the Application Verifier tool (also included in Visual Studio) will both flag this vulnerability. Finally, there are numerous training classes that cover buffer overrun vulnerabilities; it’s in the Security Basics, Code Review and Fuzzing classes. CWE-642: External Control of Critical State Data A good threat model should identify the potential for an attacker to tamper with client-side state data (T in STRIDE). Additionally, we cover in our Web security class the specific vulnerability of using hidden form fields to hold critical data. CWE-73: External Control of File Name or Path The SDL includes the following recommendations around defending against canonicalization attacks: Limit URL length to no more than 16,384 characters For managed code, use the standard System.IO classes to take advantage of built-in canonicalization defenses in the .NET framework. Avoid P/Invoking out to the Win32 file I/O APIs. Build an allow-list of valid file names or types Explicitly reject file types such as exe, bat, cmd, com, htw, ida, idq, htr, idc, shtm, shtml, stm, printer, ini, pol, dat For managed code, catch the exceptions System.ArgumentException, System.NotSupportedException, System.IO.FileNotFoundException, and System.IO.DirectoryNotFoundException For native code, prepend \\?\ to the filename (this bypasses filename equivalency checks) For URLs, check that a single pass of URL-decoding the filename matches a second pass of URLdecoding the filename. If the two decodes do not match, reject the filename. CAT.NET can flag the use of unvalidated user input as a parameter to System.IO.File and FileInfo method calls that can lead to canonicalization vulnerabilities. In addition, the SDL also recommends that web developers avoid open redirect vulnerabilities by validating all redirect targets against a predefined allow-list of known good sites or domains. Canonicalization issues are discussed in great detail in the Security Basics class. CWE-426: Untrusted Search Path CAT.NET can detect the use of untrusted user input as a parameter to System.Reflection.Assembly.LoadFile and LoadFrom methods. Additionally, our C/C++ static analysis tools such as PREfast (/analyze in Visual C++) will flag some function calls that can exacerbate the problem. Also in Windows versions beginning with Windows Server 2003 we changed the default search path ordering to not include the current directory by default. Finally, untrusted search path vulnerabilities are explained in the Security Basics class. 6 CWE-94: Failure to Control Generation of Code (aka 'Code Injection') The SDL covers one form of this attack by recommending that web developers never use the JavaScript function eval() or its functional equivalents setTimeout() and setInterval(). Using these functions could potentially allow an attacker to specify his own malicious script that would execute on the victim’s machine. Instead, the SDL asks web developers to design their applications whenever possible in such a way that dynamic code execution is not required. The evils of eval() are explained in the Web security class. CWE-494: Download of Code Without Integrity Check The SDL Threat Modeling process and tool can find these vulnerabilities: for each data flow element in the system, the modeler is prompted to brainstorm who could tweak the bits on the wire and thus perform a potential Man in the Middle (MitM) attack. To mitigate threats, the tool suggests the use of cryptographic integrity controls or any MitM defenses inherent in the OS. The threat modeling process also looks at spoofing attacks, and so potential downloads from an imposter site should also be covered. CWE-404: Improper Resource Shutdown or Release Many types of this vulnerability, including memory leaks (CWE-401), double-frees (CWE-415), use after free (CWE-416) and freeing invalid pointers (CWE-590) are found by either the Microsoft Application Verifier (appverif.exe) or the PREfast Analysis Tool, both of which are required by the SDL. Both of these tools are included with Visual Studio, and you can also download AppVerif as a free standalone tool at http://www.microsoft.com/downloads/details.aspx?FamilyID=C4A25AB9-649D-4A1B-B4A7C9D8B095DF18&displaylang=en. All the topics listed above are covered in the secure code review class. CWE-665: Improper Initialization The SDL-required PREfast static analysis tool includes checks for use of improperly initialized memory. The SDL also recommends that C++ development teams set the compiler warning level to level 4 (compiler switch /W4) and fix all resulting flagged warnings. These warnings include checks for uninitialized variables and for other issues such as signed/unsigned variable mismatches and potential data loss from type conversions. Initialization issues are discussed in the secure code review class. Additionally, the CWE/SANS guidance recommends fuzzing to test for uninitialized memory problems. The SDL requires each product to complete a large number of clean fuzzing iterations for each of the following: File format parsers (100,000 clean iterations required) RPC interfaces (24 hours of “smart” and “dumb” fuzzing without failure or memory leakage) ActiveX control methods (100 values for each parameter of each method) Network interfaces including SOAP (100,000 packets recommended) 7 CWE-682: Incorrect Calculation Our static analysis tools, most notably PREfast, will detect some forms of incorrect calculation errors. While it is not officially required or recommended by the SDL, many Microsoft teams use David LeBlanc’s SafeInt library, which provides defenses against calculation errors such as integer overflows and underflows. SafeInt is available for download on Codeplex: http://www.codeplex.com/SafeInt. The subject of arithmetic issues is taught in great detail in the Security Basics and Secure Code Review classes. Porous Defenses CWE-285: Improper Access Control (Authorization) Access control issues like elevation of privilege (EoP) and information disclosure are thoroughly addressed by the SDL threat modeling requirement. If you’re using a Data Flow Diagram (DFD) based threat modeling approach (like the SDL Threat Modeling Tool), you can use the trust boundary DFD element to divide your application into areas of appropriate privilege level. For example, resources that can be accessed by anonymous users can be separated by a trust boundary from resources that must be accessed by authenticated users, and those resources can be separated from resources that require administrative access. Access Control list (ACL) issues are covered in the Security Basics class. Ongoing education and automated analysis help us find weak object permissions as part of the SDL attack surface analysis requirements. The SDL recommendation to grant only minimal privileges by applying appropriate ACLs also helps to mitigate this vulnerability. CWE-327: Use of a Broken or Risky Cryptographic Algorithm All Microsoft products must meet the SDL cryptographic standards, which list the currently acceptable and unacceptable cryptographic algorithms. Algorithm Type Symmetric block Symmetric stream Asymmetric Hash/HMAC Unacceptable Acceptable Preferred DES, DESX, RC2, SKIPJACK SEAL, CYLINK_MEK, RC4 (<128bit or unreviewed) RSA (<2048 bit), Diffie-Hellman (<2048 bit) 3DES (2 or 3 key) AES (>=128 bit) RC4 (reviewed & >= 128bit) None – Block cipher is preferred RSA ((>=2048bit), Diffie-Hellman ((>=2048bit) SHA-2 RSA (>=2048bit) Diffie-Hellman (>=2048bit) ECC (>=256bit) SHA-2 (includes: SHA-256, SHA-384, SHA-512) SHA-0 (SHA), SHA-1, MD2, MD4, MD5 8 HMAC key lengths <112bit >= 112bit >= 128bit The Application Verifier tool will also detect the use of weak cryptographic algorithms. Cryptography training covers this topic in great detail, and the Security Basics class touches on the subject. Finally, the SDL requires products to be cryptographically “agile”; that is, they should be able to easily switch algorithms should a weakness be found in a currently acceptable algorithm. CWE-259: Hard-Coded Password The SDL cryptographic standards require developers to use the Data Protection API (DPAPI) functions CryptProtectData and CryptUnprotectData included with Windows to store all secret data, including keys and passwords. For managed code developers, DPAPI is wrapped by the .NET framework class System.Security.Cryptography.ProtectedData; the corresponding appropriate functions are Protect and Unprotect. The dangers of hard-coded passwords and related vulnerabilities such as storing passwords in a reversible format (or even storing passwords at all, in most cases) are covered in the Security Basics training class. The SDL Threat Modeling Tool similarly prompts designers to consider authentication methods that do not store secrets either on the server or the client. CWE-732: Insecure Permission Assignment for Critical Resource The SDL recommendation to grant only minimal privileges helps to mitigate this vulnerability. We’ve also built (and require the use of) internal verification tools to help find and report on system configuration errors such as weak ACLs. Access Control list (ACL) issues are covered in the Security Basics class. Training on the subject of weak permissions is in the Security Basics and Secure Design classes. CWE-330: Use of Insufficiently Random Values Insufficient randomness is yet another vulnerability covered by the SDL cryptographic standards. Pseudorandom functions like the CRT rand function or GetTickCount are banned. The only currently approved cryptographically strong random number generation functions are CryptGenRandom and rand_s for native code and the System.Security.Cryptography.RNGCryptoServiceProvider class for managed code. Use of correct random number generators is covered the Security Basics and Cryptography classes. CWE-250: Execution with Unnecessary Privileges The SDL requires teams to design their products to be used by a standard non-administrative user whenever possible. Applications must be developed with User Account Control (UAC) best practices in mind to ensure they run with least privilege. Also, applications should access resources using the 9 smallest-possible permission set; for example open an object for Read rather than Full Control when only read access is required. Least Privilege issues are covered in the Security Basics and Secure Design classes. CWE-602: Client-Side Enforcement of Server-Side Security This vulnerability has ties to both CWE-642 (External Control of Critical State Data) and CWE-20 (Insufficient Input Validation). Just as you shouldn’t trust the client to hold sensitive state data, you shouldn’t trust the client to tell you whether or not it is authorized to perform an action. The primary defense specified by the SDL against this vulnerability is threat modeling. Authentication issues in general are well covered by the SDL Threat Modeling tool, although there are no specific leading questions posed around client-side authentication/authorization vulnerabilities. Summary The following table summarizes the mapping between the SANS/CWE Top 25 and the Microsoft SDL; note that each CWE vulnerability is addressed by one or more SDL requirements: CWE Title 20 116 89 79 78 319 352 362 209 119 642 73 426 94 494 404 665 682 285 327 Education? Improper Input Validation Improper Encoding or Escaping of Output Failure to Preserve SQL Query Structure (aka SQL Injection) Failure to Preserve Web Page Structure (aka Cross-Site Scripting) Failure to Preserve OS Command Structure (aka OS Command Injection) Cleartext Transmission of Sensitive Information Cross-site Request Forgery (aka CSRF) Race Condition Error Message Information Leak Failure to Constrain Memory Operations within the Bounds of a Memory Buffer External Control of Critical State Data External Control of File Name or Path Untrusted Search Path Failure to Control Generation of Code (aka 'Code Injection') Download of Code Without Integrity Check Improper Resource Shutdown or Release Improper Initialization Incorrect Calculation Improper Access Control (Authorization) Use of a Broken or Risky Cryptographic Algorithm 10 Tools? Y Y Y Manual Process? Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Threat Model? Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 259 732 330 250 602 Hard-Coded Password Insecure Permission Assignment for Critical Resource Use of Insufficiently Random Values Execution with Unnecessary Privileges Client-Side Enforcement of Server-Side Security 11 Y Y Y Y Y Y Y Y Y Y Y Y Y Y