Software Defense is a broad topic requiring a multipronged approach including:
- the processes and tooling associated with secure development (that we try and encapsulate within the Microsoft SDL),
- core OS countermeasures that make exploitation of a given vulnerability more difficult for an attacker,
- steps to secure the hardware on which the software runs,
- real time analysis of other software on the host such as that performed by Windows Defender…
All these play a part. Our focus in this series is on the first two of these, more specifically on how the Windows operating system together with the toolchain included in Visual Studio releases together improve the state of Software Defense with respect to exploit mitigation and vulnerability detection.
Exploitation of memory safety vulnerabilities has been an area of active research, both defensive and offensive, in recent years. In this series we outline by way of examples our approach to improving the quality and resilience of code to such issues, for both Microsoft products and third party code running on Microsoft platforms.
At a high level there are two tiers of approach, summarized in the preceding paragraph by the words ‘quality’ and ‘resilience’:
We invest in exploit mitigations that will make any residual bugs in our products:
The impact of security science in protecting customers provides some historical data on the impact of past deployment of such mitigations. The value that we place on exploit mitigations is also underlined by our recently announced Mitigation Bypass bounty and BlueHat Defense program. As well as describing recent improvements in exploit mitigation, this series will highlight some of the less obvious challenges that we face during design and development, including:
- how a given measure will impact backwards application compatibility.
- performance impact in terms of runtime cost, memory overhead and code size.
The first posts in the series review how successive Windows and VC++ releases have enabled widespread hardening against heap and stack corruption vulnerabilities.
We will then move on to describe the status of generic exploit mitigations such as DEP/ASLR, aimed directly at frustrating attacker techniques, rather than any specific class of vulnerability.
Having looked at these generic approaches, the next articles will review far more targeted runtime measures against specific classes of code defects such as reference-counting issues, local elevation of privilege through kernel mode null dereferences and integer overflow bugs.
We will conclude the series by describing some of the capabilities that we’ve developed to statically detect more bugs during development through analysis of source code during compilation, thus enabling many issues to be fixed before a product ships. In particular we will focus on new security-relevant warnings in the latest Visual Studio release and how they can be applied directly in your own apps.
In order to improve accuracy and minimize noise, such detection techniques are typically highly targeted at very specific code defects: while the scope of protection is therefore limited to a specific bug class, they do however offer the potential of completely eradicating that bug class.
Balancing scope of applicability with completeness of protection is a theme that we will pick up again in more detail in later articles. We will also discuss trade-offs related to application compatibility and issues raised when considering back-porting new security advances to older platforms.
Many of the items above, taken on their own, can appear as disparate unrelated improvements. This series is an opportunity to highlight some of the connections and underlying rationale behind the various complementary approaches that we pursue along with the engineering challenges that we have faced along the way. We hope you find it interesting.
MSEC security science team