Search: Home Bugtraq Vulnerabilities Mailing Lists Jobs Tools Beta Programs
Digg this story   Add to del.icio.us  
C++: A Cautionary Tale, or, 1 Hour Of Your Black Hat Trip is Spoken For
Thomas Ptacek, Matasano 2007-07-12

1.

Almost 10 years ago, during the dot-com bubble, I did what many security pros before and after me did and “gave up on security” to “go do something meaningful” [â??]. I was at Network Associates (after they bought Secure Networks), and David Meltzer, my alter-ego at ISS, recruited me into a startup along with Danny Dulai and Tim Newsham. We wanted to build the chat system of the future, and we ended up with application-layer multicast streaming media. In 1999. We were a bit ahead of our time [â??â??].

This is good to know because it will help you avoid ever starting a discussion with me about reliable multicast protocols (down with forward error correction!) or source-specific multicast routing (down with source-specific multicast routing!). But why I bring it up is, we wrote it in C++. We wrote a lot of C++. A lot. We used ACE. Used ACE before? You know how much C++ we were swimming in. A lot of C++. Template-y, Boost-y, Alexandrescu-understandingy C++.

2.

Now this is a security blog, and so I’m supposed to be using this time to make a point about security, and that point is this: the notion that C++ is a more secure language than C is a myth. C++ gives you a dynamically-resizeable string class, which makes it less likely that you are going to write the splitvt overflow. But it also gives you a dozen new features which, if you use them wrong, segfault your program.

3.

Take exceptions. C++ has built-in support for exceptions; when something horrible happens, you “throw” a variable that any stack frame up the call chain can “catch”. This is better than returning a cryptic error code, because you can’t forget to check it.

But. When you throw an exception, you effectively “abort” your current function, and all the functions in the call chain up to the point where the exception was caught. If any of these functions aren’t written to anticipate getting preemptively aborted, and hold on to a pointer or a chunk of memory, you’ve got a memory lifecycle bug.

This problem is well known to the C++ community. Herb Sutter wrote a famous article about it, which invented the notion of “exception-safe” C++ programming. Joel Spolsky wrote a JoelOnSoftware about it. There’s a debate about whether C++ exceptions are evil.

But it’s not well known problem to the security community. A year or so ago, Mark Dowd found yet another Sendmail vulnerability. Sendmail is written in C, not C++, but it uses Unix signals and “longjmp” to emulate C++ exceptions, and (it’s Sendmail, after all) isn’t written exception-safe. You can trigger a timeout exception, and Sendmail will retain an invalid pointer into the stack that it would have cleared out if the exception hadn’t occurred. That pointer can be used to scribble over stack frames.

Any time you have a language feature, and you have to think about writing code to be “that-language-feature-safe”, you have a security problem. Because that feature is creating bug classes. Bug classes are bad. Splitvt? That’s a bug. Stack overflows? Bug class. Stack overflows cost the industry over $700MM. Exception-safety problems? Bug class. One that C++ introduces.

4.

Want another example? Destructors. Mark Dowd and John McDonald wrote a blog post about it a few months back. Do you audit code at your job? It’s one of the top #10 most valuable blog posts of the year. Long story short? If you call “delete[]” instead of “delete” —- which is an exceedingly common C++ error —- you’ve introduced a potential vulnerability. Like integer overflows, a bug class.

5.

Here’s another example: the STL. STL (or, more properly, the Standard C++ Library) is the collection of container classes C++ provides. In C, if you want a hash table, you have to implement it yourself. In C++ —- bad example. But if you want a red-black tree with the same API as a hash table, it’s provided for you. Also linked lists, resizeable arrays, and something called a dequeue (prounced “woon”). The STL is one of the great features of C++.

It’s also a reliability disaster. Here’s why: STL containers try to hide pointers from you. Instead of pointers, you get “iterators”, which are objects with a variety of interesting methods and generic functions that operate on them and all sorts of other fancy gunk and at the end of the day it’s all just 1500 lines of C++ template code wrapping: a pointer.

STL tries to avoid the most common pointer bugs, like walking off the end of an array into bad memory. But some bugs can’t be avoided. So for instance: if you modify an STL map (which is a red-black tree), you invalidate all your outstanding iterators. Modifying a red-black tree potentially repositions the nodes they pointed to, and all that fancy OOP gunk aside, iterators are just pointers, not magic. If you hold references to those invalid iterators, they now point to invalid addresses.

This is an absurdly common problem. I’m an OK developer, if I do say so myself, but Danny Dulai, Kneel Fachan, and Tim Newsham are just fucking insanely talented developers and they ran into these problems, just like me.

And again, this problem is well known in C++-world (there’s a whole very excellent book about it). But it’s not well known in the security community. And when you screw it up, it’s potentially exploitable.

6.

C++ gives you a resizeable string, so you won’t write splitvt. But in 2007, code vulnerabilities don’t look like splitvt anymore, ever. We’ve moved on, through off-by-one errors into integer overflows and now uninitialized variables. On balance, the bug classes C++ introduces are way scarier than the ones it takes off the table.

So, to kick off our series of posts about which Black Hat talks you should be going to this year, I’m going to recommend this one. Mark Dowd and John McDonald, on stage, talking about the ways C++ screws software security that you hadn’t thought of before. “Recommend” is an understatement. If you get paid to find vulnerabilities in code, this is the most valuable talk at the conference this year.

See you there!


[â??] For the most recent example of this phenomenon, see Dug Song.

[â??â??] This is marketing-speak for “wrong”; you can say the same thing for a batter’s swing when he takes a strike.


Comments


The information, views, and opinions contained on this page are those of the author and do not necessarily reflect the views and opinions of SecurityFocus.






 

Privacy Statement
Copyright 2009, SecurityFocus