Forgot your password?
typodupeerror
Security IT

New Hack Exploits Common Programming Error 255

Posted by ScuttleMonkey
from the gibson-unavailable-for-comment dept.
buzzardsbay writes "TechTarget's security editor, Dennis Fisher is reporting that researchers at Watchfire Inc. have discovered a reliable method for exploiting a common programming error, which until now had been considered simply a quality problem and not a security vulnerability. According to the article, the researchers stumbled upon the method for remotely exploiting dangling pointers by chance while they were running the company's AppScan software against a Web server. The good folks at Watchfire will detail the technique in a presentation at the Black Hat Briefings in Las Vegas in August, Fisher writes."
This discussion has been archived. No new comments can be posted.

New Hack Exploits Common Programming Error

Comments Filter:
  • by pushf popf (741049) on Monday July 23, 2007 @01:32PM (#19958527)
    Who would have thought that invalid pointers and buffer overruns might be exploitable as a security hole?

    Quick, someone alert Bill Gates!
  • by WarwickRyan (780794) on Monday July 23, 2007 @01:34PM (#19958553)
    ..is down to dangly bits.
  • by east coast (590680) on Monday July 23, 2007 @01:35PM (#19958577)
    Enough with all of this talk of "dangling pointers" you perverts.
  • The cure... (Score:5, Funny)

    by Anonymous Coward on Monday July 23, 2007 @01:38PM (#19958631)
    I found that if I stop programming every 15 minutes or so and look up some pr0n, I significantly reduced my chances of having a "dangling pointer."
  • I was sure that I'd have to read about why

    char * foo
    is a Bad Idea. The fact that I got to see that forgetting to deallocate memory was uniquely refreshing, like the spring mist in Brooklyn.


    However, I thought that the compiler took care of destroying pointers when variables went out of scope? Aren't destructors implicit clean up calls? I'm fairly sure that Borland 16-bit Turbo C++ did this, back in the day.

    • by Wavicle (181176) on Monday July 23, 2007 @01:51PM (#19958791)
      Yes and no. The pointer in question may have a lifetime greater than that of the object being pointed to. Example:


      void (*myFuncPtr)() = NULL;

      void cleanUp() {
          item listItem = firstItem;

          while ( listItem != NULL ) {

              myFuncPtr = listItem->fcn;
              myFuncPtr();

              tempItem = listItem->next;
              free(listItem);
              listItem = tempItem;
          }
      } // myFuncPtr is now dangling!


      A little contrived, sure, but it is an example of how a pointer might get left dangling.
      • Now all you need to do is be a real fool and try to call that dangling pointer.

      • by TheRaven64 (641858) on Monday July 23, 2007 @02:23PM (#19959233) Journal
        And this is where the principle of smallest scope comes into play. myFuncPtr, in your example, has no business being global, it should be declared inside the while loop so it is invalid whenever it contains invalid data. If you need it to be available outside of this block, then you make sure that everything that modifies the pointer also checks that it is valid, and is responsible for ensuring that the lifespan of the pointed object is greater than that of the pointer. Use reference counting if you don't have proper garbage collection.
        • by quanticle (843097)
          And again, that's a code quality issue, much like validating input was for buffer overflows.
  • Allan pointed out that Java-based applications are not vulnerable to this exploit because the language has a built-in mechanism for deallocating memory.

    I can see this as fodder for the argument that it's safer to run software in sandbox like Java's VM.

    • by ThinkingInBinary (899485) <thinkinginbinary.gmail@com> on Monday July 23, 2007 @01:47PM (#19958737) Homepage

      I can see this as fodder for the argument that it's safer to run software in sandbox like Java's VM.

      Um, it is fodder for that argument -- environments where memory management is handled automatically mean the programmer has one less thing to screw up. Even if you consider that the VM implementations may have errors, there are far fewer VM implementations than there are pieces of software that can run on them, so it's easier to debug a good memory manager/garbage collector for each VM than to debug the manual memory allocation and freeing in each application.

      • Garbage collected languages is no solution to poor programming. If you can't remember to not call a function pointer that you just freed, you'll probably forget to close /etc/passwd before dropping privs, or something equally stupid.

        • Garbage collected languages is no solution to poor programming. If you can't remember to not call a function pointer that you just freed, you'll probably forget to close /etc/passwd before dropping privs, or something equally stupid.

          And you could encode that kind of stuff in accessors which follow security policies, rather than directly hard coding the access and the policy every time. For example, this is why we separate code into separate processes owned by different users rather than throwing everythi

          • Well, if you're the type that can think of putting access to /etc/passwd into, say, an object that's destroyed just before dropping root, then you can probably think of a way to prevent yourself from calling dangling pointers too. And if you unit test properly, and avoid side-effects, you'll save a whole lot of trouble when you go to integrate, too.

            It's just people being lazy, hurried, or in some unfortunate cases, stupid.

            • Re: (Score:3, Insightful)

              by BitchKapoor (732880)

              Well, if you're the type that can think of putting access to /etc/passwd into, say, an object that's destroyed just before dropping root, then you can probably think of a way to prevent yourself from calling dangling pointers too. And if you unit test properly, and avoid side-effects, you'll save a whole lot of trouble when you go to integrate, too.

              It's just people being lazy, hurried, or in some unfortunate cases, stupid.

              Yes, which is why your architects and best developers create a platform on which

            • Re: (Score:3, Insightful)

              Well, if you're the type that can think of putting access to /etc/passwd into, say, an object that's destroyed just before dropping root, then you can probably think of a way to prevent yourself from calling dangling pointers too.

              Can you do both at the same time, while dealing with dozens of other headaches? Do you really want to? There's something to be said for reducing the programmer's mental workload so he can more efficiently think about the problem he's supposed to solve. Of course, making it more d

        • Garbage collected languages is no solution to poor programming.


          Eliminating the possibility of an entire class of bugs reduces the number of things that need to be remembered in putting the code together (and checked once it is coded), and therefore reduce the number of bugs (and exploitable vulnerabilities) that get through to end user code.
          • Eliminating a class of bugs is a great thing, but GC doesn't do it. Instead of memory leaks, you have object leaks. People start to trust the GC too much, and it takes away more control than it's worth. That's just a personal preference, of course, and I'll write GC code, but since I don't like it I'll take a 10% lower salary if I don't have to deal with it.

            • by Peaker (72084) <gnupeakerNO@SPAMyahoo.com> on Monday July 23, 2007 @07:00PM (#19962981) Homepage
              Leaks are logical bugs, not memory management bugs, so ofcourse GC does not eliminate them.

              GC does eliminate a few classes of bugs:
              1. A specific kind of memory leak: Of ceasing to hold references to an object, but not freeing it.
              2. Pointer arithmetic and forging is impossible, so objects cannot override each others' memory. This kind of bug creates cryptic problems that are pretty hard to debug, as they are not easily contained in a single component.
              3. In manually-managed languages, leaks can cause crashes, security problems and memory overruns, while GC converts this to an "object leak". Object leaks usually translate to a memory leak (hog problem) and only rarely cause very serious problems (as in your example of leaking /etc/passwd).
    • Well, this argument is not new. The counter argument is that the garbage collector still lets you eat up memory and causes lots of problems because of delayed destructors. Catching unfreed memory, overruns or uninitialised pointers is easy with Valgrind. (Eww, not on Windows, but well, cross platform development ftw).
  • Hehe (Score:4, Funny)

    by tttonyyy (726776) on Monday July 23, 2007 @01:40PM (#19958653) Homepage Journal
    ...which is why all my dangling pointers have unfree'd memory at the end of them just in case ;)
  • Finally (Score:4, Funny)

    by dsanfte (443781) on Monday July 23, 2007 @01:40PM (#19958661) Journal
    Finally, an indisputable reason for choosing Java over C++.
    • Re: (Score:3, Insightful)

      That's like choosing to live in a mental asylum instead of a normal home. Yeah, those padded walls are really safe, but man, anyone who exercises a little caution doesn't need that kind of thing.

      (Yes, it is a part flame in reply to another flamebait)
      • Re:Finally (Score:4, Insightful)

        by BitchKapoor (732880) on Monday July 23, 2007 @02:17PM (#19959153) Homepage Journal

        That's like choosing to live in a mental asylum instead of a normal home. Yeah, those padded walls are really safe, but man, anyone who exercises a little caution doesn't need that kind of thing.

        More like living in a gated community rather than living in the projects (the ghetto). The gated community may cost more, but it's safer than the projects, where you have to be careful not to get shot—though rather insular and not as safe as the people who live there generally think.

    • by Nasarius (593729)
      More like: restating one of the reasons that raw pointers should (almost) never be used. A reason for choosing C++ over C, perhaps.
  • by Anonymous Coward on Monday July 23, 2007 @01:42PM (#19958673)
    "Hello security hole, wanna meet my dangling pointer?"

  • Known since 2005 (Score:5, Interesting)

    by drspliff (652992) <harry.roberts@NOSPAM.midnight-labs.org> on Monday July 23, 2007 @01:43PM (#19958693)

    "When Watchfire first alerted Microsoft's security response team to what Afek and Sharabani had found, they were met with skepticism, and understandably so, Allan said. The company had known since 2005 about the IIS bug that caused the crash, but it was considered a simple denial-of-service problem and not remotely exploitable."

    Worded a little ambiguously, but I presume it's Microsoft their talking about... How can a bug like this get through the QA process since 2005 and multiple product versions without getting fixed?

    • by nagora (177841) on Monday July 23, 2007 @01:55PM (#19958863)
      How can a bug like this get through the QA process since 2005 and multiple product versions without getting fixed?

      Because people keep buying their buggy shit. If people buy your products regardless of the quality, what incentive do you have to fix anything?

    • Re: (Score:3, Interesting)

      by jimicus (737525)
      Worded a little ambiguously, but I presume it's Microsoft their talking about... How can a bug like this get through the QA process since 2005 and multiple product versions without getting fixed?

      Very easily. Every bug gets a priority assigned to it, and from the sound of things this one was ranked pretty low.

      The sheer number of bugs in any large product means it's not really practical to fix every one before a release so the higher priority ones get concentrated on. Time passes, products are realeased bec
  • And this isn't a "use Python" or "use Java" rant, either. I will say, however, UNIT TEST YOUR SHIT! EVERY LINE! Even the little inline function, you need to test it all! Repeat after me: Resource Acquisition Is Initialization. Resource Release Is Destruction. -Wall -Werror, no, warnings aren't OK. No, not even signed vs unsigned comparison warnings, you need to either get your data types straight or wrap that in a partial-specialization template functor that correctly checks that you won't be killed by sign-promotion when you compare int and unsigned long long. strncpy(), not strcpy()! -fprofile-arcs -ftest-coverage! Valgrind!

    I dunno. I manage to write C++ and never overflow a buffer, always release all resources when I'm done with them, and never throw away an error. Why can't the other 95% of the programmers out there do the same thing?

    • wrap that in a partial-specialization template functor that correctly checks that you won't be killed by sign-promotion when you compare int and unsigned long long. strncpy(), not strcpy()! -fprofile-arcs -ftest-coverage! Valgrind!

      Whoa there, cowboy. Them's fightin' words.
      • Yeah, I just read that again. Guess I got a little carried away...

      • by Intron (870560)
        strncpy is a frequent cause of code bugs and inefficiency:

        1) It does NOT guarantee that it creates a NULL-terminated string.

        2) It always writes every byte of the destination. Copy 10 characters into a 1000-byte buffer and it writes 1000 bytes, mostly zeros.
    • by PetriBORG (518266) on Monday July 23, 2007 @02:00PM (#19958939) Homepage

      I dunno. I manage to write C++ and never overflow a buffer, always release all resources when I'm done with them, and never throw away an error. Why can't the other 95% of the programmers out there do the same thing?

      They are busy being yelled at by their boss to "just make it work" and to "not worry about getting it perfect" and they are dealing the idiot "build master" over in change-management who doesn't know what "make clean" is or how to read a make file, but thinks that he's some master csh hacker... Everyone wants that just not everyone works in a perfect world.

      Shit, most of us are just happy when we are able to beat clear requirements out of people and get reasonable bug reports.

    • by BitchKapoor (732880) on Monday July 23, 2007 @02:03PM (#19958977) Homepage Journal

      I dunno. I manage to write C++ and never overflow a buffer, always release all resources when I'm done with them, and never throw away an error. Why can't the other 95% of the programmers out there do the same thing?

      Because they don't care or they're too busy with other stuff, and even if that's not the case, sometimes people make mistakes. That's why you write tools to check that programs are actually being written correctly (wherever possible) and to make it as easy as possible to create full coverage tests, rather than relying on other programmers to do the right thing. Automation, it's a great thing.

    • by Red Flayer (890720) on Monday July 23, 2007 @02:03PM (#19958981) Journal

      I manage to write C++ and never overflow a buffer, always release all resources when I'm done with them, and never throw away an error. Why can't the other 95% of the programmers out there do the same thing?
      So, you're saying you program properly, but the other 19 programmers in existence can't?

      Something tells me that even if your programming is 100% spot-on, your grammar skills are slightly lacking...
      • I'm sorry, you're right, there's way more than 20 of us out there. What I should have said is, why can't the other 1,999,999%?

        No, wait...

    • What's the biggest project you've worked on?
    • by 140Mandak262Jamuna (970587) on Monday July 23, 2007 @02:34PM (#19959423) Journal
      Why can't the other 95% of the programmers out there do the same thing?

      Because the other 95% saw that you take too long to write code and your code executes too slowly and you are going to be fired because of it.

      • Re: (Score:3, Insightful)

        Because the other 95% saw that you take too long to write code and your code executes too slowly and you are going to be fired because of it.

        Don't be silly. It is perfectly possible to write robust, efficient C++ code at a decent speed. And it is certainly much more efficient than generating buggy crap and then spending weeks, months and years trying to find the elusive bugs. Not to mention the complete rewriting of large blocks of unintelligible, bad-quality code as 'bug fix'.

        I fully agree with the ori

    • by slackmaster2000 (820067) on Monday July 23, 2007 @02:37PM (#19959469)
      "I dunno. I manage to write C++ and never overflow a buffer, always release all resources when I'm done with them, and never throw away an error. Why can't the other 95% of the programmers out there do the same thing?"

      Because we're employed.
    • by RAMMS+EIN (578166)
      ``Why are we still dealing with this?

      And this isn't a "use Python" or "use Java" rant, either. I will say, however, UNIT TEST YOUR SHIT! EVERY LINE!''

      You don't think that writing in a language that just doesn't allow these bugs to be coded would be easier? Not to mention that that would actually guarantee the absence of such bugs, which unit testing doesn't?
    • by Chyeld (713439)
      Probably because their not on their 20th nervous breakdown. (it's a joke, but there is a point to it.)
    • Re: (Score:3, Insightful)

      strncpy(), not strcpy()

      You do realize that strncpy() is fundamentally broken, right? If the source string is longer than n characters, then the destination string will not get a null terminator. The first operation after that on the destination string will go flying off the end with unpredictable results. strncpy() is also inefficient in that it will fill the dest buffer with unnecessary null characters if the source is short. I use my own strcpy() function that takes the size of the destination-string

    • Re: (Score:3, Informative)

      by Nevyn (5505) *

      As someone who's written 2 pieces of OSS with 100% code coverage in unit tests, and probably the most secure C http server (comes with over 75% coverage). I have to say: "It's not quite that simple". Testing does not negate design, and designing for security is non-trivial and takes a certain mind-set ... and while a lot of people say they want security, almost none are actually prepared to buy it (with either money, lack of features, whatever).

      Hell, one of the biggest advancements in security in rece

  • what a headache (Score:3, Informative)

    by circletimessquare (444983) <circletimessquare@gmail. c o m> on Monday July 23, 2007 @01:51PM (#19958793) Homepage Journal
    it's one thing to find a major exploit, but a whole new class of exploits?

    welcome back to the days of sql slammer and code red folks. buffer overflows have been analyzed to death, but this is just the beginning
    • No, this is very little new. It's the same basic programming error that's been made since day one, "whoops, I forgot." Not to mention, there's absolutely no explanation on how they've managed to put code in what's basically an arbitrary memory location.

      But man, this type of thing should be a 0.01% of software type of bug. What the hell? Isn't software engineering?

  • by kwerle (39371) <kurt@CircleW.org> on Monday July 23, 2007 @01:55PM (#19958861) Homepage Journal
    This is a story about a company that says they have a story.

    Let's just wait until the actual story next time? (since it doesn't seem likely there will be a real one, here, anyway)
  • by steveha (103154) on Monday July 23, 2007 @02:03PM (#19958985) Homepage
    I have written a bunch of C code, and a little C++ code.  I have made it a habit to set a pointer to NULL after I free the pointer's data.  If I had code that allocates a FOO structure, I would make a function to free the FOO structure; in C, my FreeFoo() function would not take a pointer to a FOO, but a pointer to a pointer to a FOO, and after freeing the FOO it would set the pointer to NULL.  Like so:

    /* C code */

    void
    FreeFoo(PFOO *ppfoo)
    {
        PFOO pfoo;

        assert(NULL != ppfoo);
        if (NULL == ppfoo)
            return;

        pfoo = *ppfoo;

        assert(NULL != pfoo);
        if (NULL == pfoo)
            return;

        free(pfoo);
        *ppfoo = NULL;
    }

    /* typical use:

    PFOO pfoo = PfooNew(args);
    ...do something with FOO object...
    FreeFoo(&pfoo);
    */

    Note that if you acidentally try to double-free the FOO, the above code will not crash; the first free sets the FOO pointer to NULL, and the second one notices that the pointer is already NULL and exits early.  It does assert() when you try to free a NULL pointer, so you can catch the error and see what else you might have messed up.

    For C++ you should be able to write a template that takes a reference to any pointer type and applies the above logic.

    I once had to maintain a legacy code base, a whole bunch of C implementing a fairly complicated application.  The app had a whole bunch of crashing bugs.  I went through and applied the above logic everywhere the app was calling free() and suddenly the app stopped crashing.  I wonder if the previous developers were using a different compiler or something, and the dangling pointers just happened to work for them?

    steveha
    • Exactly! I'm no fan of C, there's too much I've gotten used to being able to do in C++, but this just goes to show that while you can write crap code in any language, you can write good code too.

      Good on ya for putting your lvals on the right of your comparisons, too.

      • by cerelib (903469) on Monday July 23, 2007 @02:36PM (#19959461)
        Just curious, what is advantage to putting your lvalues on the right of a comparison? Is it an optimization or just a "best practice"? I typically will put the subject of the comparison on the left. Which means between a constant/literal and an lvalue, the lvalue gets the left. Between to lvalues, I pick the one, which there almost always is, that is somehow more important to the logic of the control statement being compared for. I am a professional programmer, but have never heard of any rule or advantage regarding lvalues on the right of a comparison.
    • by BitchKapoor (732880) on Monday July 23, 2007 @02:13PM (#19959085) Homepage Journal
      Unfortunately, that solution breaks down when you have multiple different pointer variables pointing to the same location. This will happen in any graph-like data structure more advanced than a tree. You can get around it by adding a level of indirection from handles to pointers, and making the handle-pointer mapping nodes reference counted (note that reference count cycles are not possible using this strategy), but that can have a significant performance hit, and requires quite a bit of refactoring.
      • Unfortunately, a hammer does you no good when you're omg standing on the surface of the sun! so we should throw away all the hammers.

        I think he was just trying to illustrate a simple point, not post the One True Memory Management pattern :P

      • by steveha (103154) on Monday July 23, 2007 @02:47PM (#19959619) Homepage
        Unfortunately, that solution breaks down when you have multiple different pointer variables pointing to the same location.

        Okay sure, the FreeFoo() logic will not, by itself, take care of the case where you have multiple pointers. Only the pointer you actually use to free the object would be automatically nulled.

        As you note, it is possible to pass around "handles" and make the handles safe, and as you note, there can be a performance hit.

        But if you have a clean code design, you will have an expected lifetime for those extra pointers, and when you are done using a pointer, you can NULL that pointer. When you are done, you should have only one pointer left pointing to the object, and when you call FreePfoo(), you will then have zero pointers left pointing to the now-freed object.

        Another simple trick you can use: at the beginning of your structure, place a member variable called "signature" or something like that, and set it to some unique value. Then, in FreePfoo(), zero out the signature before you call free(). Then start each function that uses a PFOO with an assert() that checks that the signature is sane. Even if you have a dangling pointer, and even if that pointer can still be used to reference your structure after you free() the structure, the assert() will fail. If you like you can put the "signature" member under #ifdef so that you don't even compile it in unless asserts are enabled.

        The last major application I developed, I used the above tricks. The most important data structures each had their own unique signature. Functions that took a PFOO started with a call to AssertValidPfoo(pfoo), which would check the signature and also perform every other sanity check I could think of upon the FOO and the pointer (and which would not be compiled for a release build). Once the compile succeeded with no errors or warnings, I would run a test and immediately get an assert() if I had a code bug. Once I fixed the code to no longer assert(), in general my code Just Worked.

        Asserts are like unit tests that run every time you run your code, and don't cost anything in the final release build. I love asserts.

        Does this sound like more work than a garbage-collected language like Java or Python? Well, it is. C is just plain a lower-level language and you need to do more stuff by hand.

        steveha
    • Re: (Score:3, Insightful)

      by jgrahn (181062)

      I have made it a habit to set a pointer to NULL after I free the pointer's data. If I had code that allocates a FOO structure, I would make a function to free the FOO structure; in C, my FreeFoo() function would not take a pointer to a FOO, but a pointer to a pointer to a FOO, and after freeing the FOO it would set the pointer to NULL.

      It's something people often suggest, and I don't like it at all. It doesn't catch the serious case, where you have more than one pointer to the memory. Who is going to null

  • ....programming?

    Let's ignore plugins or modules, because those are frequently C/C++; however, it's been my experience that writing modules is far less common than just implementing code in PHP or Perl. I'm talking about basic application logic, generally form processing and serving HTML content.

    I have implemented barebones C and C++ HTTP servers because high performance was a critical requirement, but the percent gain wasn't really worth the effort. PHP with caching (apc, memcached, db pooling) is alm
    • by el_womble (779715)
      The interesting thing about web programming is that it's rarely the application itself that is slowing the system down. Disk I/O, network and database speed are far more likely to be the bottleneck than the application. That's why web programmers get away with the likes of Hibernate, Ruby on Rails, J2EE etc and games programmers don't, and if thats not the case, the code is so naturally multi-threaded that app server problems can normally be solved by buying another box far quicker than they can by implemen
  • You have a pointer.

    You free the the object the pointer is pointing too.

    The bad guy figures out where the pointer is pointing and writes his code at that location. The next time the pointer is called the bad code is executed.

    This is like saying you lock a door and put the key away somewhere. The bad guy finds the key, unlocks the door and takes what he wants.

    Why is this suddenly a major security issue and what am I missing?
    • The bad guy figures out where the pointer is pointing and writes his code at that location. The next time the pointer is called the bad code is executed.

      (emphasis mine)

      Why is this suddenly a major security issue and what am I missing?

      The bad guy typically has no control over where the pointer is pointing (that's determined by the memory management library). The bad guy also cannot write whatever he wants into arbitrary memory locations. If he could, he would already have complete control over the process and wouldn't need to exploit anything.

      That's why this type of problem has typically been considered nearly impossible to exploit. There's too many variables that the attacker can't control (and memory management can

      • Re: (Score:3, Informative)

        by mr_mischief (456295)
        I guess the issue is, since they say "predictably" instead of "always", that there's a decent probability when one takes automation of the exploit into account. Try this enough times, and eventually you get it to work. It only takes the one time to "pwn" the server.
  • by Schraegstrichpunkt (931443) on Monday July 23, 2007 @02:48PM (#19959629) Homepage

    From the article:

    Dangling pointers are quite common, but security experts and developers have said for years that there is no practical way to exploit them, so they've been considered quality-assurance problems and not security flaws.

    Any security expert with at least half a brain is going to assume that a remotely-triggered crash might be exploitable, unless he can actually prove otherwise.

    That said, I've known plenty "security experts" who weren't.

  • <lots of noise here>

    "Common programming error"?

    The foo! Just tell us WHICH error, will ya?!? /me calms down a bit

    Ok, I know a few lines further on they actually did, but the beginning just ticked me off. This is a bloody tech site, I'd think that some people here _would_ know what you're talking about when you say "dangling pointer".
  • by hey (83763)
    How do they know its an dangling pointer?
    Could by anyone of a hundred possible bugs.
  • Those guys used the wrong term. When I hear dangling pointers, I often think structs that have pointers to other stuff and the struct has been freed before its pointers are freed. What these people say is dangling pointers are merely pointers to stuff that's been freed but the references have not been reset to NULL. Resetting them to NULL is basic C-programming 101.
  • Exploit (Score:3, Interesting)

    by Anonymous Coward on Monday July 23, 2007 @03:34PM (#19960279)
    After discussing it with a fellow developer, here's what we thought might be happening:
    1. Application allocates a C++ object, deletes it, but continues to point to it. The exploit code is likely to force this condition. The attacker has to know the type (and size) of the C++ object.
    2. Exploit code sends a packet to the server causing it to allocate memory of exactly the same size as the C++ object that was deleted and store the exploit payload in that memory. For example, in case of a web server it might be an HTTP request of size X or an HTTP request with multiple HTTP headers of size X, depending how the implementation stores whatever it receives on port 80.
    3. The heap allocation algorithm would presumably re-use the space that was deallocated when the C++ object was deleted. The exploit payload is copied over into the allocated buffer, examined and discarded (e.g. the payload is not valid HTTP). This is OK since the dangling pointer is still pointing to the memory area with the exploit payload.
    4. Now the exploit causes the dangling pointer to be used to reference a virtual function and it's game over.

    The exploit payload needs to act like a virtual table. It can reference exploit code in itself or jump somewhere in the running process which would make it exploitable (e.g. "DeinitializeSecurity" function).

    Hopefully the paper is more interesting than this.

  • From TFA... (Score:5, Funny)

    by Sebastopol (189276) on Monday July 23, 2007 @03:52PM (#19960563) Homepage
    "This is a bit of a Pandora's box and once we open it, it will be just the tip of the iceberg."

    Did anyone else think:

    "If we hit that bullseye, the rest of the dominoes will fall like a house of cards! Checkmate." - Zapp Brannigan

  • Not news for Mozilla (Score:5, Informative)

    by jesser (77961) on Monday July 23, 2007 @05:05PM (#19961637) Homepage Journal
    Mozilla has considered dangling pointer use to be "probably exploitable to run arbitrary code" for a long time. I even blogged about that fact [squarefree.com], describing what types of dangling point use are most likely to be exploitable. If other software companies refuse to prioritize those bugs until the reporter supplies a demonstration exploit that launches calc.exe or Calculator.app, they've been asking for trouble for years.

No skis take rocks like rental skis!

Working...