Phase 3: Implementation
The Implementation phase is when the end user of your software is foremost in your mind. During this phase you create the documentation and tools the customer uses to make informed decisions about how to deploy your software securely. To this end, the Implementation phase is when you establish development best practices to detect and remove security and privacy issues early in the development cycle.
On This Page
Creating Documentation and Tools for Users That Address Security and Privacy
Establish and Follow Best Practices for Development
Creating Documentation and Tools for Users That Address Security and Privacy
Every release of a software program should be secure by design, in its default configuration, and in deployment. However, people use programs differently, and not everyone uses a program in its default configuration. You need to provide users with enough security information so they can make informed decisions about how to deploy a program securely. Because security and usability might conflict, you also need to educate users about the threats that exist and the balance between risk and functionality when deciding how to deploy and operate software programs.
It is difficult to discuss specific security documentation needs before development plans and functional specifications stabilize. As soon as the architecture is reasonably stable, the user experience (UX) team can develop a security documentation plan and schedule. Delivering documentation about how to use a software program securely is just as important as delivering the program itself.
Development management, program management, and UX teams should meet to identify and discuss what information users will need to use the software program securely. Define realistic use and deployment scenarios in functional and design specifications. Consider user needs for documentation and tools.
User experience teams should establish a plan to create user-facing security documentation. This plan should include appropriate schedules and staffing needs. Communicating the security aspects of a program to the user in a clear and concise fashion is as important as ensuring that the product code or functionality is free of vulnerabilities.
For new versions of existing programs, solicit or gather comments about what problems and challenges users faced when securing prior versions.
Make information about secure configurations available separately or as part of the default product documentation and/or help files. Consider the following issues:
The program will follow the best practice of reducing the default attack surface. However, what should users know if they need to activate additional functionality? What risks will they be exposed to?
Are there usage scenarios that allow users to lock down or harden the program more securely than the default configuration without losing functionality? Inform users about how to configure the program for these situations. Better yet, provide easy-to-use templates that implement such configurations.
Inform users about security best practices, such as removing guest accounts and default passwords. External security notes from threat modeling are good sources of information to consider.
For programs that use network or Internet communications, describe all communications channels and ports, protocols, and communications configuration options (and their associated security impacts).
To support earlier versions of the software and older protocols, it is often necessary to operate less securely. Do not enable insecure protocols in the default configuration. You might still need to deliver them with the release, so inform users about the security implications of older protocols and backward compatibility. Inform users about these trade-offs and how to disable older compatibility modes to achieve the best possible security.
Tell users how they can ensure safe use of the program or take advantage of built-in security and privacy features.
If the program contains privacy controls, create deployment guides for organizations to help them protect their users’ privacy (for example, Group Policy controls).
Create content to help users protect their privacy when using the program (for example, secure your subnet).
The Security Development Lifecycle (ISBN 9780735622142; ISBN-10 0-7356-2214-0), Chapter 10: Stage 5 – Creating Security Documents, Tools, and Best Practices for Customers
Templates contained in the Windows Server 2003 Security Guide
Establish and Follow Best Practices for Development
To detect and remove security issues early in the development cycle, it helps to establish, communicate, and follow effective practices for developing secure code. A number of resources, tools, and processes are available to help you accomplish this goal. Investing time and effort to apply effective practices early will help you eliminate security issues and avoid having to respond to them later in the development cycle—or even after release, which is expensive.
(Promoted for SDL 5.2) Components must have no hard dependencies on the NTLM protocol. All explicit uses of the NTLM package for network authentication must be replaced with the Negotiate package. All client authentication calls must provide a properly formatted target name—service principal name (SPN). The purpose of the requirement is to enable systems to use Kerberos in place of NTLM whenever possible.
(Promoted for SDL 5.2) HTTPOnly Cookies. To mitigate the risk of information disclosure with a cross-site scripting attack, a new attribute was introduced to cookies for Internet Explorer 6 Service Pack 1 (SP1) and is now in use in all current browsers. This attribute specifies that a cookie is not accessible through script. By using HTTP-only cookies, a web application reduces the possibility that sensitive information contained in the cookie can be stolen via script. Watcher, a web security testing tool, can help you meet this recommendation.
Set-Cookie: USER=123; expires=Wednesday, 10-Feb-2012 23:12:40 GMT; HttpOnly"
Use minimum code generation suite and libraries. For unmanaged, native C/C++ code, use Visual C++ 2010 as it offers all the SDL-mandated compiler and linker flags, including /GS, /DYNAMICBASE, /NXCOMPAT, and /SAFESEH. For managed code, use Visual Studio® 2008 SP1 or later. Use the currently required (or later) versions of compilers to compile options for the Win32®, Win64, WinCE and Macintosh target platforms, as listed in Appendix E: SDL Required and Recommended Compilers, Tools, and Options for All Platforms. The biggest change in Visual Studio 2008 SP1 and later is Data Execution Prevention (DEP) support, enabled by default for all binaries, which can help protect against classes of buffer overrun. For unmanaged C or C++ code, BinScope must indicate a "Pass" in the compiler version field for all binaries. For managed code, an attestation is required that the compiler version used to ship the product is the version outlined in this document or later.
Code analysis tools. Use the currently required (or later) versions of code analysis tools for either native C and C++ or managed (C#) code that are available for the target platforms, as listed in Appendix E: Required and Recommended Compilers, Tools, and Options for All Platforms. Run PREfast for Drivers on all kernel-mode driver source code. File bugs for each instance of each warning as required by the SDL and triage based on tool output. Ensure that all appropriate bugs are fixed.
Banned Application Programming Interfaces (APIs). All native C and C++ code must not use banned versions of string buffer handling functions. Based on analysis of previous Microsoft Security Response Center (MSRC) cases, avoiding use of banned APIs is one actionable way to remove many vulnerabilities. For more information, see Security Development Lifecycle (SDL) Banned Function Calls and The Security Development Lifecycle (ISBN 9780735622142; ISBN-10 0-7356-2214-0), Chapter 19: SDL Banned Function Calls, pp. 241-49.
No writable shared PE sections. Sections marked as shared in shipping binaries represent a security threat. Use properly secured dynamically created shared memory objects instead. See Appendix G: SDL Requirement Shared Sections.
For online services and/or LOB applications, follow data input validation and output encoding requirements to address potential cross-site scripting vulnerabilities.
For online services and/or LOB applications that access a SQL database, do not use “ad-hoc” SQL queries in order to avoid SQL injection attacks.
For online services and/or LOB applications that implement web services, use an approved XML parser.
Fix issues identified by code analysis tools for managed code. Run the FxCop code analysis tool against all managed code, and fix all violations of the “Security” rules for the version of FXCop used. Note that there are slight differences in the security rules for FXCop 1.35 (from Visual Studio® 2005) and FXCop 1.36 (from Visual Studio 2008). These differences are explained in the Code Analysis Team Blog. When using .NET Framework version 3.5, FXCop 1.36 must be used. Security rules for FXCop can be found at http://msdn.microsoft.com/en-us/library/ms182296(VS.80).aspx. Security rules for FXCop can be found at http://msdn.microsoft.com/en-us/library/ms182296.aspx.
Compile native code with /GS compiler. All unmanaged C and C++ code must be compiled with the /GS compiler option. /GS- (which turns off /GS) is not allowed. Verify all build files include the /GS compiler option so that all native code C and C++ binaries are compiled using this option. High-risk code (code facing the Internet, file parsers, and ActiveX controls) must have #pragma strict_gs_check(on) in an application-wide header file, such as stdafx.h. Ensure no buffers are marked as safebuffers. Verify there are no instances of compiler warning C4748.
Address Space Layout Randomization (ASLR) must be enabled on all native code (unmanaged) binaries to protect against return-to-libc class of attacks. Enabling this functionality requires the flag /DynamicBase in the PE header of all binaries. This flag can be inserted using Visual Studio 2005 SP1 or later. Earlier versions do not contain a linker version that supports it. DumpBin can be used to manually verify if ASLR is enabled on a binary.
Do not use banned APIs. Problems arise when an attacker controls the incoming buffer, and the code uses data from the buffer to determine the maximum buffer length to copy. Verify there are no banned APIs in shipping code, including sample code. Recommended tool: banned.h header or use of Visual C++ use of C4996 warnings.
- Use secure methods to access databases. Creating dynamic queries using string concatenation potentially allows an attacker to execute an arbitrary query through the application. Verify that all database access is performed through a combination of parameterized inline queries, stored procedures (activated through parameterized queries or LINQ), or object names passed to Windows Azure Storage APIs that are not based on user-provided data.
- If directly calling the Windows Azure Storage Blob REST APIs, all parameters should be URL-encoded with AntiXSS.Urlencode. When calling Windows Azure Table APIs, WCF Data Services should be used rather than writing REST queries directly.
- The database is accessed via a least-privilege account with only the minimum level of access required to carry out the application's functions. This account must never have system administrator (SA), database owner (DBO), or other administrative privileges.
Avoid LINQ ExecuteQuery. LINQ queries are normally converted by the compiler/framework into parameterized queries to be passed to the database. However, the LINQ method ExecuteQuery allows the developer to pass arbitrary SQL commands that may have been created through string concatenation. Creating dynamic queries using string concatenation potentially allows an attacker to execute an arbitrary query through the application. This vulnerability allows for unauthorized, interactive logon to a SQL server that may result in the execution of malicious commands leading to the possible disclosure, modification, or deletion of the operating system or user data.
Calls to System.Data.Linq.DataContext.ExecuteQuery are prohibited. If you are using LINQ, use the standard LINQ object-relational mapping (ORM) syntax or stored procedure syntax.
Examples of correct code/procedures
Correct ORM: from product in Products select productCorrect stored procedure: SelectProducts()
Example of incorrect code:
ExecuteQuery("SELECT * FROM Products")
The exit criteria for this requirement is that your code contains no references to System.Data.Linq.DataContext.ExecuteQuery.
Avoid EXEC in stored procedures. The stored procedures contain no calls to EXEC. EXECUTE or sp_executesql (except for calls to other stored procedures).
Do not use Microsoft Visual Basic® 6 to build products. Make sure that all Visual Basic code in the product, including sample code, is built with Visual Basic .NET and not Visual Basic 6. No product distributes or uses the runtime environment for Visual Basic 6. When running BinScope, confirm it reports no instances of binaries built with Visual Basic 6.
- Harden or disable XML entity resolution. XML parsing code can be vulnerable to exponential entity expansion attacks and external entity resolution attacks causing denials of service and disclosure of sensitive data. If XML entity resolution is not required by your application, then disable it. Verify that all XML parsing code (including use of XmlReader and XmlDocument) do one of the following:
- Completely disable entity resolution.
- Limit the size of internal entity resolution and disable external entity resolution if it is not possible to disable entity resolution.
- Limit the size of internal entity resolution and limit the time and size of external entity resolution if it is not possible to disable external entity resolution.
Use safe integer arithmetic for memory allocation for new code. All new code that uses arithmetic to determine the amount of dynamic memory to allocate must be safe from any form of overflow, underflow, or truncation.
Use secure cookie over HTTPS. HTTP cookies created over HTTPS should not be visible to the same site over clear text via HTTP. Ensure that all cookies set over HTTPS use the "secure" attribute. Suggested tools include: Watcher (from Casaba Security).
AllowPartiallyTrustedCallersAttribute (APTCA) review. Ensure that the AllowPartiallyTrustedCallersAttribute (APTCA) enables an assembly to be called by untrusted code. APTCA behavior is different depending on the version of the framework, but the general effect is the same: potentially dangerous functionality is now exposed to partially trusted code, and the effects of this additional attack surface exposure have to be mitigated by security checks, strong enforcement mechanisms, and review. Ensure there is no code using APTCA or that your project exception review process has approved a request to use APTCA.
- Mitigate against cross-site request forgery (CSRF). Cross-site request forgery is a type of attack in which a malicious website exploits the user’s browser to send commands to another website. This attack exploits the victim site’s trust in the user’s browser, generally by using the user’s cookies or session
- For ASP.NET or ASP.NET MVC projects, verify that all pages in the application report no AlwaysSetViewStateUserKeyTokenValue or MarkVerbHandlersWithValidateAntiforgeryToken FxCop rule violations.
- For non ASP.NET projects, verify that:
- A secondary token is submitted with each request. Ideally, the token must be unique per user, though session-unique tokens will suffice.
- Validation tokens are not automatically submitted (such as via cookie). Including a hidden input value in a POST is the preferred method.
- The token is not predictable. If the attacker can predict the token, it negates the protection.
Load DLLs securely. Applications and dynamic-link libraries (DLLs) must load DLLs securely to prevent DLL preloading vulnerabilities.
Minimum ATL Version and Secure COM Coding Requirements. Developers using the Active Template Library (ATL) to build COM controls must make sure they use the most secure ATL versions and use appropriate secure ATL coding constructs. Verify that the latest version of the ATL library is used and all ATL code is implemented with the correct secure coding constructs. This can be verified by passing the ATLVersionCheck and ATLVulnCheck tests with BinScope.
- Reflection and authentication relay defense. This new recommendation is designed to help combat sophisticated toolkits that are available to implement reflection and relay attacks. It is hoped that it will aid developers in utilizing available defenses against reflection and authentication relay attacks. For network authentication, the following tasks should be followed:
- Specify the target system name as part of the authentication mechanism.
- Ensure channel integrity through signing and/or encrypting underlying transport messages using the negotiated session key, or implement Extended Protection for Authentication when signing or encryption is not supported.
Sample code should be SDL compliant. All sample code (code snippets, small sample applications, or complete sample applications) should meet the same SDL development practices security bar as if it were in a shipping product. That means all the appropriate tools must be run, and there is no use of banned functionality or compiler switches.
Internet Explorer 8 MIME handling: Sniffing OPT-OUT. This recommendation addresses functionality new in Internet Explorer 8 that may have security implications in some cases. It is recommended that for each HTTP response that could contain user controllable content, you utilize the HTTP Header X-Content-Type-Options:nosniff. The Watcher tool may be of use in meeting this requirement
Safe redirect, online only. Automatically redirecting the user (through Response.Redirect, for example) to any arbitrary location specified in the request (such as a query string parameter) could open the user to phishing attacks. Therefore, it is recommended that you not allow HTTP redirects to arbitrary user-defined domains.
- Comply with minimal Standard Annotation Language (SAL) code annotation recommendations as described in Appendix H: SDL Standard Annotation Language (SAL) Recommendations for Native Win32 Code. Annotating code helps existing code analysis tools identify implementation issues better and also helps improve the tools. SAL annotated code has additional code analysis requirements, as described in SDL SAL Recommendations
Establish and document development best practices for the development team. Communicate any design changes that affect privacy to your team’s privacy lead so that they can document and review any changes
Use HeapSetInformation. Use Windows heap corruption detection to help reduce the likelihood of successful exploitation of residual heap-based vulnerabilities.
Review available information resources to adopt appropriate coding techniques and methodologies. For a current and complete list of all development best practice information and resources, see Writing Secure Code, Second Edition (ISBN 9780735617223; ISBN-10 0-7356-1722-8).
Review recommended development tools and adopt appropriate tools.
Define, document, and communicate to your entire team all best practices and policies based on analysis of all the resources and tools listed in this document.
- Document all tools that are used, including compiler versions, compile options (for example, /GS), and additional tools used. Also, forecast any anticipated changes in tools. For more information about minimum tool requirements and related policy, review How Are New Recommendations and New Requirements Added to the Security Development Life Cycle Process?
- Create a coding checklist that describes the minimal requirements for any checked-in code. This checklist can include some of the items from Writing Secure Code, Second Edition "Appendix D: A Developer’s Security Checklist” (p. 731), clean compile warning level requirements (/W3 as minimal, and /W4 clean as ideal), or other desired minimum standards.
- Establish and document how the team will enforce these practices. Is the team running scripts to check for compliance when code is checked in? How often do you run analysis tools? The development manager is ultimately responsible for establishing, documenting, and validating compliance of development best practices.
Additional development best practices for security can be divided into three general categories:
- Review available information resources to adopt coding techniques and methodologies that are appropriate for the product.
- Review recommended development tools to adopt, and use those that are appropriate for the product, in addition to the tools required by the SDL.
- Define, communicate, and document all best practices and policies for the product. Based on analysis of all of the resources and tools listed above, product teams should adopt and communicate best practices, policies, and tools. This information should be documented and widely communicated to the entire product team to ensure best practices are adopted and followed.
Document all tools used. This includes all compiler versions, compile options (for example, /GS), and additional tools used for static code analysis. This should also forecast any changes in tools anticipated. As updated versions of tools (both compilers and code analysis tools) are made available, products that have not yet released a final beta will likely be required to adopt the newest version of the tools. Products that have released their final beta prior to the availability of updated tools are not required to adopt the latest versions of tools. Please review How Are New Recommendations and New Requirements Added to the Security Development Lifecycle Process? for more information on how policy is established on minimum tool requirements.
Use the Windows Imaging Component (WIC). WIC provides an extensible framework for reading and manipulating images, image files, and image metadata. It represents a standard interface. All software products that process digital image data must perform any encoding or decoding of image data solely and exclusively using the Windows Imaging Component (WIC) and therefore must remove any potential custom (image) codecs from the product codebase. For more information, see http://msdn.microsoft.com/en-us/library/ee719654.aspx
Ensure that regular expressions must not execute in exponential time (O(2^n)). Regular expressions that are evaluated against untrusted input must be examined for unsafe patterns that can lead to denial-of-service (DoS) vulnerabilities. Use RegexFuzzer to analyze all regular expressions to ensure that they are free of grouping expressions with repetition that are themselves repeated and containing alternation where the alternate sub-expressions overlap each other.
Use proper http.sys URL canonicalization. Web servers often make security decisions based on a requested URL from a user. For example, a web server may deny access to certain files, such as configuration files, directly through the web server; rather, such files can only be viewed and manipulated with text editing tools, such as Visual Studio, against the local file system. The weakness with this approach is that the authorization check is based on the name of the resource, rather than based on an access control mechanism, such as an ACL, enforced by the operating system. And this leads to canonicalization (C14N) vulnerabilities, because there is often more than one way to name a resource. All web servers have suffered from such issues, but http.sys does not offer much protection from C14N vulnerabilities. It is therefore important that developers using http.sys follow these recommendations to defend themselves. Any application that uses http.sys should follow these guidelines.
- Limit the URL length to no more than 16,384 characters (ASCII or Unicode). This is the absolute maximum URL length, based on the default IIS 6 setting. Web sites should strive for a length shorter than this, if possible.
- Use the standard .NET Framework file I/O classes (such as FileStream), since these take advantage of the canonicalization rules in the .NET FX.
- Explicitly build an allow-list of known filenames.
- Explicitly reject known filetypes you will not serve; UrlScan rejects: exe, bat, cmd, com, htw, ida, idq, htr, idc, shtm[l], stm, printer, ini, pol, dat files.
- Catch the following exceptions: System.ArgumentException (for device names), System.NotSupportedException (for data streams), System.IO.FileNotFoundException (for invalid escaped filenames), and System.IO.DirectoryNotFoundException (for invalid escaped dirs).
- Do not call out to Win32 file I/O APIs.
- On an invalid URL, gracefully return a 400 error to the user, and log the real error.
- Limit the URL length to 16,384 characters (ASCII or Unicode).
- Prepend \\?\ to the filename prior to accessing the file system, since this forces the file system to bypass filename equivalency checks. This is not perfect, because it does not prevent data streams (::$DATA, for example).
- Normalize the URL by URL double-decoding the filename, and check that the first decode matches the second decode. If not, it's an error.
- Look for known “bad characters” in the filename.
- Look for known “bad strings” in the filename.
- On an invalid URL or filename, return a 400, and log the real error.
Use Standard Annotation Language (SAL). Annotate all functions that read from or write to a buffer passed as an argument to the function.
Enforced automated banned API replacement. Add the following to an often-used header file, such as stdafx.h:
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES (1)
This informs the compiler that you want to upgrade various C runtime functions to safer versions. For example, some calls to strcpy will upgrade to strcpy_s. For more information on banned APIs, visit http://blogs.msdn.com/sdl/archive/2008/10/22/good-hygiene-and-banned-apis.aspx.
- Encode long-lived pointers. Long-lived pointers (for example, globally scoped function pointers or pointers to shared memory regions) are subject to corruption through a buffer overrun attack that can lead to code execution attacks. This recommended defense raises the bar substantially on the attackers.
Identify any long-lived pointers in your code. Access to these functions should be through encoded pointers using code like this:
// g_pFoo is a global point that points to foo void g_pFoo = EncodePointer(&foo); // Now get the encoded pointer void *pFoo = DecodePointer(g_pFoo);
The global pointer (g_pFoo) is encoded during the initialization phase, and its true value remains encoded until the pointer is needed. Each time g_pFoo is to be accessed, the code must call DecodePointer.
Fix code flagged by /W4 compiler warnings. Attackers are finding and exploiting more obscure classes of vulnerabilities as traditional stack and heap buffer overruns become harder to find. To this end, it is recommended that all W4 warning messages are fixed prior to release.
No global exception handlers. Exceptions are a powerful way to handle run-time errors, but they can also be abused in a way that could mask errors or make it easier for attackers to compromise systems.
Restrict database permissions. Only grant "execute" permission on all stored procedures, and grant that permission only for the application domain group. For example:
- Run your online service as "Network Service," for example, phx\$machinename
- Join that domain account to a domain group, for example, phx\mywebappgroup
Ensure that the application database is set for execute permission only (and no other permissions) on its stored procedures and those permissions are associated with a domain group of which that application or server is a member. The principle of least privilege should be used and the group associated with the online service should not be granted access to any other object and no other user or group should be used within the online service for communication with the SQL server.
NULL out freed memory pointers in new code. This helps reduce the severity of double-free bugs and bugs that overwrite "dangling" pointers. For example:
char *p = new char[N]; ... delete  p;
Add this statement after the delete operator:
p = NULL;
The same process applies to any dynamic allocation and freeing pattern (for example, using malloc/free, GlobalAlloc/GlobalFree, or VirtuaAlloc/VirtualFree).
Lock ActiveX controls to a defined set of domains. Identify any ActiveX controls, new and existing, that can be locked to a preselected set of domains, and incorporate the SiteLock 1.15 Template for ActiveX Controls during implementation to lock each control to that set of domains. Note that each control can have its own set of domains.
ClickJacking defense. For each page that could contain user controllable content, you should use a "frame-breaker" script and include the HTTP response header named X-FRAME-OPTIONS in each authenticated page. The Watcher tool may be of use in meeting this recommendation. The exit criteria for this recommendation is as follows:
- A "frame-breaker" script is included in each authenticated page to prevent unintentionally framing.
- The X-FRAME-OPTIONS header has been added to all authenticated page HTTP responses that should not be framed (for example, DENY) or is utilized to only allow trusted sites to frame site content (for example, the current site with the use of SAMEORIGIN).
COM best practices. Check for HRESULT misuse and uninitialized [PROP]VARIANTs. All HRESULTs should be set to valid COM values, (such as S_OK, S_FALSE, or E_FAILED) and all VARIANTs are initialized correctly.
Restrict database permissions. Only grant Execute permission on all stored procedures, and grant that permission only for the application domain group. For example, run your online service as Network Service (for example, phx\$machinename) or join that domain account to a domain group (for example, phx\mywebappgroup).
Make sure that this group is granted execute permissions only on your stored procedures. The principle of least privilege should be used and the group associated with the online service should not be granted access to any other object (and no other user or group should be used within the online service for communication with the SQL server).
Use Transport Layer encryption securely. Properly use Transport Layer Security (TLS) when communicating with another entity, and verify that your service checks the Common Name attribute to be sure it matches the host with which you intended to communicate. Verify that your service consults a CRL for an updated list of revoked certificates at a frequent interval. If your service is accessible via a browser, verify that no security warnings appear at any visited URL for any supported browser.
The Security Development Lifecycle (ISBN 9780735622142; ISBN-10 0-7356-2214-0), Chapter 11: Stage 6 – Secure Coding Policies, Chapter 19: SDL Banned Function Calls
This documentation is not an exhaustive reference on the SDL process as practiced at Microsoft. Additional assurance work may be performed by product teams (but not necessarily documented) at their discretion. As a result, this example should not be considered as the exact process that Microsoft follows to secure all products.
This documentation is provided “as-is.” Information and views expressed in this document, including URL and other Internet website references, may change without notice. You bear the risk of using it.
This documentation does not provide you with any legal rights to any intellectual property in any Microsoft product. You may copy and use this document for your internal, reference purposes.
© 2012 Microsoft Corporation. All rights reserved.