Michael Howard had an interesting
piece the other day on the SDL blog and also gave an
interview about some similar topics. The subject I'd like to address is the banning of certain things during the development process and the theoretical and practical aspects of it. I'd like to show that banning function calls and enforcing annotations as a coding practice is reasonably far down the path to saying that C/C++ isn't such a good programming language from a security perspective and that to achieve higher levels of assurance we need to go further down that road.
I'd like to touch on a few points in this piece:
- The SDL vs. Legacy Code
- Banning Programming Constructs, Functions, and/or Whole Languages
- A Sliding Scale of Assurance
The SDL vs. Legacy CodeOne of the things I'm struck by in Microsoft's SDL book is how pragmatic it is with respect to making software more secure. They point out repeatedly in the SDL book that products have been delayed and features scrapped because they either weren't secure, or couln't be made secure. While I can't argue with them about whether they've done this, there are at least a few places that we can point out a less than stellar track record of reducing feature sets to improve security. Web Browsers and how Windows does file associates come to mind as big security vs. feature wars that the feature folks seem to have won.
Michael and the other folks at Microsoft have done a ton of good work in creating, refining, and implementing their secure software development methodology, SDL. The SDL however reflects the realities of the Microsoft situation - millions of lines of legacy code. No one with that much legacy code can afford to start over from scratch. Anyone who suggested writing the next version of Word in All C# would probably get a swift kick. So, the Microsoft security folks are left with taking the practical approach. Given the fact that there is a lot of legacy code, and given that they aren't going to make a wholesale switch to another programming language, what is the best they can do in C++.
I think this is a fair approach but I don't really believe for a minute that if you asked one of the security guys there what programming language they want new things written in they'd pick C++ over C# for anything other than things like a kernel.
Banning Programming Constructs, Functions, and/or Whole LanguagesMichael said in his recent piece:
In all of our SDL education we stress the point that .NET code is not a security cure-all, and we make sure that developers understand that if you choose to ignore the golden rule about never trusting input no language or tool will save you. Using safe string functions can help mitigate risks of buffer overruns in C/C++, but won’t help with integer arithmetic, XSS, SQL injection, canonicalization or crypto issues. The key point is that languages are just tools; anyone using a tool needs to understand the strengths and limitations of any given tool in order to make informed use of the tool.
One final thought; in my opinion, well-educated software developers using C/C++ who follow secure programming practices and use appropriate tools will deliver more secure software than developers using Java or C# who do not follow sound security discipline.
I can't argue with Michael's point. I also don't know a lot of people in the security world that believe eliminating C/C++ automatically makes you secure. I do know quite a number of people though that make the good case that programming in C# or Java significantly reduces the exposure to certain classes of vulnerabilities and overall results in more secure software when using a develop trained in security.
WhiteHat Security's numbers of the general presence of web application security vulnerabilities per language seems to bear this out. In general applications written in ASP.NET and Java have fewer security vulnerabilities in them due to language constructs and secure coding frameworks.
I think you only have to look at what Microsoft has done with banning certain functions and requiring annotations to see that they have already taken some steps in the -
C++ is bad - direction.
Why do they ban certain function calls such as strcpy, etc? Is it because the function inherently cannot be used safely? No. The reason is that its tremendously hard to use safely, and by removing it from the programmers options and replacing it with something that is easier to use, they improve the security of their software.
Why do they do annotations? They do them so that their static analyzers have an easier time in ferreting out certain classes of security defects.
If we could train developers to use all of the features of the programming language correctly, we wouldn't have to worry about either of these things. We'd simply do training and get on our way. The reality is that we cannot rely on developers to use certain portions of the language properly. We've shown repeatedly that certain function calls are the root of the vast majority of the security vulnerabilities out there. Most of the function calls that Microsoft has banned are ones that have been found to result in buffer overflows.
If we take as our starting position that developers can and will make mistakes, and we're wiling to enforce certain rules on them to constrain how they can use a programming language, why not take the next step and ask what else we can do to improve the security of the code we deliver?
There are several other areas of C++ that are problematic from a security perspective. Memory allocation comes to mind. The number of flaws we see from misuse of memory allocation is huge. Why not switch to a language that makes it fundamentally harder or impossible to have these kinds of issues?
Take the annotations Microsoft is using to hint their static analyzers. What these amount to are lightweight programming-by-contract constructs that we use for after-the-fact analysis rather than just forcing them through the programming language and calling violations errors. why not switch to a programming language that forces annotations rather than treating them as an after-the-fact construct?
A Sliding Scale of AssuranceIn the end what we have is a sliding scale of assurance and functionality. Processes such as the SDL that mandate processes but don't require us to switch tools only get us so far down the assurance path. It is further than many/most companies are willing to go and credit to Microsoft for making such an effort. At the same time there are things the SDL doesn't necessarily do:
- Enforce the use of tools and programming languages that are more likely to reduce security vulnerabilities
- Eliminate software features that are truly problematic from a security standpoint and yet users have come to expect
If we want the SDL to be about delivering fundamentally more secure software at higher assurance levels, then it must mandate certain programming methodologies that result in higher quality code. Without these sorts of mandates we're still just putting band-aids on our existing software development processes.
Assurance comes at a cost. Development costs, testing costs, etc. When we switch tools that eliminate certain classes of vulnerabilities both remove the effort that developers would spend on securing the code, and also on the time the testers spend looking for certain classes of defects. In the end this is what Microsoft has done by removing certain programming constructs, they just haven't made the slightly bigger jump to another programming language for reasons I've already explained above.
UpshotWhat I think this comes down to is use C++ if you must to muck with legacy code, but please don't do new development there. From a security perspective its going to be a lot more expensive if you do.