Slashdot Mirror


New Hack Exploits Common Programming Error

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."

67 of 255 comments (clear)

  1. Well duhhhh. by pushf+popf · · Score: 5, Funny

    Who would have thought that invalid pointers and buffer overruns might be exploitable as a security hole?

    Quick, someone alert Bill Gates!

    1. Re:Well duhhhh. by abradsn · · Score: 3, Insightful

      Hmm, actually there are entire languages that have built in features to avoid this problem. It is indeed a known problem, and it is indeed very old. Whoever wrote the article saying that this was new as a security issue, is quite misinformed. Actually, since they are writing an article, that makes them an idiot too. Too many journalist idiots out there that don't ask more than 1 person a question before taking it at down as factual. I don't know any programmer that would have said, "Oh, dangling pointers, memory leaks, and bad code... those aren't security problems." Unless of course, they are joking.

  2. All the trouble in this world.. by WarwickRyan · · Score: 4, Funny

    ..is down to dangly bits.

    1. Re:All the trouble in this world.. by Herkum01 · · Score: 2, Funny

      That is why I use button fly, much harder for dangling bits to expose themselves.

    2. Re:All the trouble in this world.. by Opportunist · · Score: 2, Funny

      Will people never learn? Security by obscurity doesn't work!

      --
      We used to have a Bill of Rights. Now, with the rights gone, all we have left is the bill.
  3. I'm telling my mother! by east+coast · · Score: 4, Funny

    Enough with all of this talk of "dangling pointers" you perverts.

    --
    Dedicated Cthulhu Cultist since 4523 BC.
    1. Re:I'm telling my mother! by fbjon · · Score: 3, Funny

      Does "damp security holes" sound better?

      --
      True confidence comes not from realising you are as good as your peers, but that your peers are as bad as you are.
    2. Re:I'm telling my mother! by Vintermann · · Score: 2, Funny

      Security by obscenity doesn't work!

      --
      xkcd is not in the sudoers file. This incident will be reported.
  4. The cure... by Anonymous Coward · · Score: 5, Funny

    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."

  5. Hehe by tttonyyy · · Score: 3, Funny

    ...which is why all my dangling pointers have unfree'd memory at the end of them just in case ;)

    --
    biopowered.co.uk - catalytically cracking triglycerides for home automotive use since 2008. Just say no to big oil!
  6. Finally by dsanfte · · Score: 4, Funny

    Finally, an indisputable reason for choosing Java over C++.

    --
    occultae nullus est respectus musicae - originally a Greek proverb
    1. Re:Finally by A+beautiful+mind · · Score: 2, 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)

      --
      It takes a man to suffer ignorance and smile
      Be yourself no matter what they say
    2. Re:Finally by BitchKapoor · · 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.

      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.

  7. a new pickup line... by Anonymous Coward · · Score: 3, Funny

    "Hello security hole, wanna meet my dangling pointer?"

  8. Re:That's nice and everything but.... by Wavicle · · Score: 5, Insightful

    Presumably what they have here is a dangling pointer to a function, which they can get IIS to then call. They state that this used to be a "denial of service" attack - meaning that if IIS attempted the call before, it would execute garbage and cause a runtime fault. Now, however, they can change the value of the dangling pointer and when IIS does the jump this time, it executes their exploit code instead.

    --
    Education is a better safeguard of liberty than a standing army.
    Edward Everett (1794 - 1865)
  9. Known since 2005 by drspliff · · Score: 4, Interesting

    "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?

    1. Re:Known since 2005 by nagora · · Score: 4, Insightful
      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?

      --
      "Encyclopedia" is to "Wikipedia" what "Library" is to "Some people at a bus stop"
    2. Re:Known since 2005 by jimicus · · Score: 2, Interesting

      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 because there are deadlines and business needs and it's quite possible that something could be ranked at such a low priority that it never gets any real attention.

  10. Re:More push toward VM's by ThinkingInBinary · · Score: 3, Insightful

    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.

  11. Why are we still dealing with this? by 19thNervousBreakdown · · Score: 4, Insightful

    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?

    --
    <xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
    1. Re:Why are we still dealing with this? by PetriBORG · · Score: 5, Insightful

      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.

      --
      Pete/Petri "damn, my chainsaw is clogged with 1's and 0's again." --clyde
    2. Re:Why are we still dealing with this? by BitchKapoor · · Score: 4, Insightful

      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.

    3. Re:Why are we still dealing with this? by Red+Flayer · · Score: 4, Funny

      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...
      --
      "Trolls they were, but filled with the evil will of their master: a fell race..." -- J.R.R. Tolkien on Olog-hai
    4. Re:Why are we still dealing with this? by 19thNervousBreakdown · · Score: 2, Funny

      Yeah, I just read that again. Guess I got a little carried away...

      --
      <xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
    5. Re:Why are we still dealing with this? by 140Mandak262Jamuna · · Score: 4, Informative
      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.

      --
      sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
    6. Re:Why are we still dealing with this? by slackmaster2000 · · Score: 4, Funny

      "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.

    7. Re:Why are we still dealing with this? by Red+Flayer · · Score: 3, Informative

      No, it's a syntax error. "The other 95% of programmers" refers to the complete set of programmers, less excluded subset. He defined that subset as himself, instead of himself plus others who can code properly; improper usage of "The other" is what caused his dependent clause to be false.

      Note that I'm using dependency grammar here (to which class algebraic grammar belongs). Followers of looser grammatical theories may find the statement technically correct since his meaning was clear. However,this is predominatly a tech site, it follows that dependency grammars should rule the roost.

      --
      "Trolls they were, but filled with the evil will of their master: a fell race..." -- J.R.R. Tolkien on Olog-hai
    8. Re:Why are we still dealing with this? by Citizen+of+Earth · · Score: 2, 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 buffer as a parameter.

    9. Re:Why are we still dealing with this? by Nevyn · · Score: 2, Informative

      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 recent years is SELinux, and I see almost nothing but complaints about how it "is less usable, so we just turn it off". Summary: We are still dealing with security problems because that's what the majority of the market wants, welcome to democracy and the free market.

      strncpy(), not strcpy()!

      Actually usage of strncpy() almost certainly guarantees you have bugs, IMNSHO. You need a real managed string API. Assuming the programer can keep track of three distinct pieces of information like "size, length and pointer" is just a losing bet. All of the applications (including mine) that have had security guarantees with money have internally used a real managed string API.

      --
      ustr: Managed string API with ave. 44% overhead over strdup(), for 0-20B
    10. Re:Why are we still dealing with this? by psmears · · Score: 2

      No, it's a syntax error. "The other 95% of programmers" refers to the complete set of programmers, less excluded subset. He defined that subset as himself, instead of himself plus others who can code properly; improper usage of "The other" is what caused his dependent clause to be false.

      You can argue all you like, but it's still not a syntax error. It is, I grant you, not strictly speaking the correct choice of words—but since one could make the statement 100% correct by changing the situation (i.e. by systematically killing off programmers in their thousands until only 20 remain in the world[1]), but without changing the phrase, it is most certainly a gramatically correct sentence—even if the semantics are wrong in the given context.

      [1] This would, of course, be taking the phrase "grammar nazi" to a whole new level...

    11. Re:Why are we still dealing with this? by Mutatis+Mutandis · · Score: 2, 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 original author. Buffer overruns? Dangling pointers? I haven't had them in years, and my code is written on time and meets performance targets. Nor am I even that skilled a C++ writer; I do something from time to time to keep in good mental form, and when I need to integrate some fast processing code in Java code or enterprise software. I have no respect for people who allow buffer overruns or dangling pointers to pollute their code, and who leak memory from all their gills. All it takes to prevent such errors is a little care, the adoption of reasonable design patterns, and a bit of mental exertion.

      There are plenty of more-or-less excusable bugs, let's start by learning to avoid to inexcusable ones.

      And I am especially annoyed at the so-called 'safe' versions of standard library functions that MS introduced in Visual C++ to compensate for this kind of libertine amateurism, even deprecating strncpy()... in favor of a version that is best avoided unless you are well aware what it is doing to the rest of your buffer. But then the Microsofty version of C++ has always been a definite example of a language that has gone over to the dark side.

  12. Re:Pleasantly surprised! by Wavicle · · Score: 5, Interesting

    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.

    --
    Education is a better safeguard of liberty than a standing army.
    Edward Everett (1794 - 1865)
  13. what a headache by circletimessquare · · Score: 2, Informative

    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

    --
    intellectual property law is philosophically incoherent. it is your moral duty to ignore it or sabotage it
  14. FUD! We're important! by kwerle · · Score: 2, Insightful

    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)

  15. Re:More push toward VM's by 19thNervousBreakdown · · Score: 5, Insightful

    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.

    --
    <xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
  16. NULL those pointers, folks by steveha · · Score: 3, Interesting

    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

    --
    lf(1): it's like ls(1) but sorts filenames by extension, tersely
    1. Re:NULL those pointers, folks by BitchKapoor · · Score: 3, Informative

      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.

    2. Re:NULL those pointers, folks by cerelib · · Score: 3, Insightful

      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.

    3. Re:NULL those pointers, folks by 19thNervousBreakdown · · Score: 3, Insightful

      It prevents the common mistake of using the assignment operator "=" when you meant the equality operator "==". I like it better your way too, since it illustrates the object of the comparison better, but if I'm rushing out code that I don't have time to write good unit tests for, I switch over.

      --
      <xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
    4. Re:NULL those pointers, folks by steveha · · Score: 3, Informative

      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

      --
      lf(1): it's like ls(1) but sorts filenames by extension, tersely
    5. Re:NULL those pointers, folks by jgrahn · · Score: 2, Insightful

      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 those pointers? A clear design which explicitly takes object lifetimes into account is a much better solution.

      (I also don't like the PFOO typedef in your example. Pointers are important in C; hiding the fact that something is a pointer will only lead to more bugs, at least if someone other than yourself will maintain the code. It will also make it impractical to say "pointer to const FOO", thus hurting type safety.)

  17. Re:That's nice and everything but.... by mark-t · · Score: 4, Insightful

    But wouldn't said exploit code need to reside in a part of memory that the operating system had previously allocated for executable instructions? I mean I can understand how you could potentially make code that was already part of the program execute without the intention of the programmer, but how do you make code that isn't part of the executable in the first place execute? I mean sure you can put the opcodes for particular instructions into data space, but if you try to branch there, why would the OS even allow that unless the area the program uses for data is also marked as an area where executable instructions can be?

  18. Re:That's nice and everything but.... by TheRaven64 · · Score: 4, Informative

    The OS has very little to do with it. It's the hardware, specifically the MMU, which will do this checking. If you are using something like OpenBSD, then it will not let a page be both executable and writeable at the same time, but that requires doing some messy things with segments on x86 (unless you have a new chip with page-level execute permissions). On most x86 hardware, if memory is readable, it is executable, and anything you allocate with malloc() and friends will have read/write/execute permissions.

    --
    I am TheRaven on Soylent News
  19. Re:More push toward VM's by BitchKapoor · · Score: 2, 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. 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 the rest of your developers can relatively easily instantiate individual solutions. There's more than one programmer working on any sizeable project.

  20. Re:Pleasantly surprised! by TheRaven64 · · Score: 3, Insightful

    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.

    --
    I am TheRaven on Soylent News
  21. Re:SOS? by quanticle · · Score: 2, Informative

    People have been 'sploiting this kind of thing for years as far as I know.

    Perhaps you're confusing dangling pointers with buffer overflows. Buffer overflows occur when you put too much data into a pre-allocated buffer, overwriting the return address of the current function with a return address pointing to your malicious code. Dangling pointers are simply pointers pointing to invalid types. Before, it was thought that dangling pointers were not exploitable, because you had to know the actual type of the destination object, which was thought to be difficult. However, this group has discovered a way to reliably discover the destination type, allowing them to overwrite it with malicious code.

    --
    We all know what to do, but we don't know how to get re-elected once we have done it
  22. Not an Apache issue. by Ayanami+Rei · · Score: 3, Informative

    Apache doesn't really work in a way that leaves dangling pointers to exploit in the first place (resource pools). And since this requires code to be loaded at a specific point in memory, which then must be executed, it's going to be webserver-build and OS-specific, which leaves Apache in a good position since that varies across distributions and versions; the attack will be useless if grsecurity or other address randomization technique is used.

    IIS 5.1 and 6.0 is a smaller target space of possibilities.

    --
    THIS THING CAN TURN ON A DIME, MACROSSZERO STYLE ALSO FUCK BETA, ~NYORON
  23. "Security experts" that aren't by Schraegstrichpunkt · · Score: 4, Insightful

    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.

  24. Re:That's nice and everything but.... by Wavicle · · Score: 2, Insightful

    How the heck do you get a dangling function pointer in C or C++? You never malloc() or operator new() functions, unless you fancy self-modifying code.

    Oh fine, be pedantic about it. Put the pointer in a struct and maintain a dangling pointer to the struct. All pointers within the struct are now dangling as well, including function pointers. An attacker can then (theoretically) change the value of the function pointer. This is the C equivalent of the C++ attack you describe. If someone attempts to call the function based off the dangling struct pointer, the exploit succeeds.

    --
    Education is a better safeguard of liberty than a standing army.
    Edward Everett (1794 - 1865)
  25. Re:That's nice and everything but.... by TropicalCoder · · Score: 4, Informative

    Now, however, they can change the value of the dangling pointer and when IIS does the jump this time, it executes their exploit code instead.

    They are not saying they "change the value of the dangling pointer".

    From the FA: "The problem before was, you had to override the exact location that the pointer was pointing to. It was considered impossible. But we discovered a way... The long and short of it is, if you can determine the value of the pointer, it's game over."

    There are theoretically two ways to exploit a dangling pointer - change the address that it points to (which they don't do), or discover the address it is pointing to, and put some code there (considered impossible). Most likely, it is pointing to memory space within the program that once held valid executable code. They say this "was considered impossible, but we discovered a way". So I suspect they just stuck a jump instruction at the location the pointer was pointing to instead of trying to cram executable code into an unknown sized space. The jump would of course be to some space they allocated, with a known size, big enough to hold their exploit. Determining the value of the dangling pointer would be easy enough - you would get a message when it crashed that the app tried to access invalid memory at addr: 0x????????. Just stick a jump at that location - then get a big warm hug from Microsoft when you show them how you did it.

  26. - It doesn't have to be a function pointer. by DogFacedJo · · Score: 5, Interesting

    In OO languages a pointer to an object works almost as well. The object pointed to in many implementations begins with a type field. This is usually a pointer to the class's virtual function table - usually implemented as a table of function pointers.
        That is to say - if the object is referenced through a bad pointer, *and executes* any methods of that object's type - then it could be used to run someone elses code. They'll need to have filled some memory with something that can be interpreted as a virtual function table that points at something that can be interpreted as code. Which is doable.
        If the processor/OS has set an app to able to write to it's executable memory, then it is vulnerable to this class of vulnerability.
        Many OS's and C++, Objective C and *java* implementations default to this.

    Pascal and perl used (maybe they still do) stubby things that required that the *stack* be executable, nevermind just data... *buffer overruns* are much easier when the stack is executable.

        Java is interesting. Modern VMs do a lot of dynamic optimization - this means that they write on code that is actually running. They need OS permission to do so (in decent OSs?) so now you *have* to give the VM's process that permission in order to run Java. Now any dangling pointers in the VM implemention are potentially exploitable. Or if the memory manager has a bug and improperly deallocates an object... Or if the application has to call a library and that library accidentally accesses a reference to an object that was already released by java. Or maybe the app calls the OS - and the OS has a dangling pointer (say to a data structure that the Java VM needed to allocate). If you can fill the Java heap with executable exploit data, then if someone, anyone, jumps into it - they are toast.

      I hope this helps. There is likely an actual paper that they will present. It will document one or several of the myriad ways to exploit dangling pointers - hopefully more efficiently than previously.

    1. Re: - It doesn't have to be a function pointer. by DogFacedJo · · Score: 3, Informative

      Sure almost every *chip* is capable of preventing simultaneous write and execute... but it is rare for the OS to be configured that way due to the surprising number of applications that want to write on code. VMs, in particular - Java, flash, .NET, custom library loaders in databases and web-servers, script interpreters in any sufficiently fancy application often optimize by throwing in a little code generation.
          While, in theory, all this stuff can be done by only writing on code when it is created or loaded - and then changing the flags back to execute-only to run it... but big apps frequently want fine-grained control over which code to rewrite, and even the ability to patch instructions that another CPU might be about to execute.
          Why is this needed? Take an example - a VM wants to be able to recompile frequently executed code *after* startup - probably at a function/method level since code all over the place might be calling into any particular class implementation. Having recompiled the subject code - all the code running should be migrated over to the new faster implementation. If you have to *stop* the system every time you do this, a lot of the performance advantages of dynamic recompilation get eaten - and it totally bollixes 'realtime' implementations (so do most of the garbage collecters, but not *all* thankfully).
          So Either - the instructions that are calls to the old code have to actually be indirect off of function-pointers - always even for non-virtual code, and some big virtual function tables merely need to be updated on recompilation, or you allow static invocations - and have rewrite the call instructions underneath the running CPUs.
          Thing is - na indirect (or virtual) function call *is* slower than a direct one - an extra memory access is required, and in big apps it is not reasonably to assume that code will usually be in cache - an extra dependent memory access is *not* the 'one tick' that some theorists claim - it can hit many hundreds of ticks in pathological situations - without even hitting disk.
          So... while they don't *have* to have write on code ... big applications want it for performance reasons.

    2. Re: - It doesn't have to be a function pointer. by EdwinFreed · · Score: 3, Informative

      I'm not enough of a Perl expert to say anything about its implementation requirements, but there's nothing in the either original or Extended Pascal that requires code execute on the stack, at least not on most machines. If this technique is used it is almost always simply an implementation choice, nothing more.

      The place where this sort of trickery is useful in Pascal is when a routine passes a routine at an "inner" lexical scope to another routine. In order for the passed routine to access variables in its outer scope it needs a pointer to the stack frame of the containing (in the lexical sense) routine. This cannot be assumed to have anything to do with the routine that ends up calling the passed routine.

      One way to implement this is to have the code passing the routine to another routine build a stub on the stack that sets up the pointer properly before calling the real routine. The address of this stub is then passed instead of the actual routine's address.

      A much better way in most cases is to pass both the address of the routine and the pointer to the stack frame, either as two separate parameters or else as a pointer to a structure that contains both. (On OpenVMS, for example, such structures were called Bound Procedure Values or BPVs.) The routine that ends up calling the passed routine then uses the pointer in the bound procedure value to set things up for the actual routine before calling it.

      The main problem with this approach is that it is incompatible with how most non-lexically-scoped languages pass references to routines around. It can be done in such a way that things work as long as the passed routine doesn't actually use any variables in the outer scope, which is usually good enough. In any case, the risks of having the compiler always put code on the stack would seem to me to be much greater than this small inconvenience.

      I once wrote a routine (in VAX assembly) that acted as a shim between a Pascal routine passing a procedure or functon paramter to a routine in another language. This code used the BPV to construct a stub on the stack which it then passed along. This let me call, say, an quadrature routine written in FORTRAN with the function being integrated coded in Pascal. I used this trick very sparingly, however.

      As for Java, I'm not sure "interesting" is the right term. I've read through some descriptions of the tricks it uses and they frankly scare me.

    3. Re: - It doesn't have to be a function pointer. by DogFacedJo · · Score: 2, Interesting

      Definitely an implementation choice for Pascal - but it (according to legend) was not a *rare* one - especially on x86 era implementations. 'Trampolines' I heard they called those stubs... didn't recheck this, so feel free to enlighten me.

          BPVs... I had thought Pascal still used something similar, but double checking, it seems those were just a VMS-iness. Pascal's scoping certainly enabled some profound hells in my life ... it is truly amazing what an incompetent developer can do with what was at first glance merely an 'interesting' language feature...

          As for Java - in the context of wild jumps and security vulnerabilities, the crazy VM implementations floating around are _surely_ interesting. ;}

    4. Re: - It doesn't have to be a function pointer. by Vintermann · · Score: 2, Informative

      http://gcc.gnu.org/onlinedocs/gccint/Trampolines.h tml

      It usually involves stack execution, but that can apparently be avoided with a little extra cost. It's not language specific, but compiler-specific.

      --
      xkcd is not in the sudoers file. This incident will be reported.
  27. Re:That's nice and everything but.... by lgw · · Score: 2, Informative

    Various version of Window support DEP (Data Execution Protection?), and for Server 2003 with the lastest SP, I believe all of Windows itself runs under DEP. You have the option to enforce DEP on all running software, but chances are something you need will break. I don't know if it's possible to enforce DEP on some application and not others.

    --
    Socialism: a lie told by totalitarians and believed by fools.
  28. Exploit by Anonymous Coward · · Score: 3, Interesting

    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.

  29. Re:That's nice and everything but.... by lgw · · Score: 3, Interesting

    I betting it's the C++ vtables exploit suggested by the previous thread. If you have a C++ class with a virtual function, the freed memory has a pointer to a table of pointers to executable code. Changing that vtable pointer to point to a malicious vtable might work.

    I'm not sure why that would work better with dangling pointer than pointers to live code, however - how do you change the memory that the pointer points to without already having access? Presumably that's what these guys discovered: a way to get a buffer allocated and filled with user data at the spot the dangling pointer points.

    --
    Socialism: a lie told by totalitarians and believed by fools.
  30. From TFA... by Sebastopol · · Score: 4, Funny

    "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

    --
    https://www.accountkiller.com/removal-requested
  31. Re:Dangling Pointers alone?? by Chirs · · Score: 2, Interesting

    Nope, because they get freed when it exits.

    In short-running programs with no persistant side effects (sysv shared memory, semas, or msg queues, for instance) there's really nothing wrong with letting the OS clean up after you.

  32. Re:More push toward VM's by The+One+and+Only · · Score: 2, 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 difficult does make it easier for more talented programmers to find work since less talented programmers would be forced out of the profession...

    --
    In Repressive Burma, it's not just your connection that dies. slashdot.org/comments.pl?sid=314547&cid=20819199
  33. Re:That's nice and everything but.... by SteveAyre · · Score: 3, Informative

    But that's actually Windows supporting the NX bit on certain recent CPUs. It *needs* hardware support to work properly.

    There is a software substitute which takes effect in case your CPU doesn't support the NX bit, but that only prevents some attacks and *won't* stop execution of code in data pages.

  34. Re:That's nice and everything but.... by SteveAyre · · Score: 2, Informative

    I don't know if it's possible to enforce DEP on some application and not others.

    And the answer is yes, it is possible. Windows runs DEP in either an Always-on, Always-off, Opt-in or Opt-out modes. Opt-out lets you enable DEP by default and then override it for specific programs which break, and Opt-in lets you disable it by default and then enable it for specific programs which'll benefit such as a web server.

  35. Not news for Mozilla by jesser · · Score: 4, Informative

    Mozilla has considered dangling pointer use to be "probably exploitable to run arbitrary code" for a long time. I even blogged about that fact, 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.

    --
    The shareholder is always right.
  36. Re:What is this? by mr_mischief · · Score: 2, Informative

    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.

  37. Re:That's nice and everything but.... by tricorn · · Score: 3, Informative

    Well, no - a dangling pointer implies two different pointers referencing the same memory area. Since many objects have pointers to other objects, if you can change one object by modifying fields through the other pointer (either the dangling pointer or the memory area doubly referenced), you can change one of those object pointers to point to a location on the stack; then using common buffer overflow techniques, you can put code on the stack and modify a return address to point to that code.

    I wouldn't say such an approach can ALWAYS be used to compromise a machine, but it is much more generic than the (also quite possible) C++ (and similar language) specific method using pointers to vtables and such.

    I've always assumed that if you can get a program to crash, you can probably get it to execute arbitrary code. One way of avoiding such techniques (other than writing correct code) is to use hardware support. The No-Execute page flag is one good start; having separate control-flow and data stacks would be another (where the control-flow stack would only be accessible through special instructions). Randomizing the location of the stack and the heap, and possibly make the memory allocation routine be less optimal and more random would also help a lot. Having a tagged memory architecture would be helpful as well (pointers to code could ONLY be manipulated through special instructions, and trying to load the wrong type of memory would cause a hardware exception).

  38. GC does eliminate bugs by Peaker · · Score: 3, Interesting
    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).