Follow Slashdot stories on Twitter

 



Forgot your password?
typodupeerror
×
Security IT

New Hack Exploits Common Programming Error 255

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 Wavicle ( 181176 ) on Monday July 23, 2007 @01:42PM (#19958677)
    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.
  • 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.

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

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

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

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

  • Re:Finally (Score:3, Insightful)

    by A beautiful mind ( 821714 ) on Monday July 23, 2007 @02:02PM (#19958971)
    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)
  • 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 mark-t ( 151149 ) <markt AT nerdflat DOT com> on Monday July 23, 2007 @02:04PM (#19958995) Journal
    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?
  • 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 BitchKapoor ( 732880 ) on Monday July 23, 2007 @02:22PM (#19959205) Homepage Journal

    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.

  • 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 Anonymous Coward on Monday July 23, 2007 @02:29PM (#19959339)
    That's actually a semantic error, not a syntactic one.

    Oops, sorry, must have had -pedantic turned on.

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

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

  • by jgrahn ( 181062 ) on Monday July 23, 2007 @02:53PM (#19959685)

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

  • by Wavicle ( 181176 ) on Monday July 23, 2007 @02:53PM (#19959691)
    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.
  • by Citizen of Earth ( 569446 ) on Monday July 23, 2007 @03:04PM (#19959829)

    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.

  • by The One and Only ( 691315 ) * <[ten.hclewlihp] [ta] [lihp]> on Monday July 23, 2007 @04:17PM (#19960937) Homepage

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

  • by Mutatis Mutandis ( 921530 ) on Monday July 23, 2007 @07:38PM (#19963379)

    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.

  • Re:Well duhhhh. (Score:4, Insightful)

    by abradsn ( 542213 ) on Monday July 23, 2007 @09:10PM (#19964155) Homepage
    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.

8 Catfish = 1 Octo-puss

Working...