×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

New Hack Exploits Common Programming Error

ScuttleMonkey posted more than 6 years ago | from the gibson-unavailable-for-comment dept.

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

cancel ×
This is a preview of your comment

No Comment Title Entered

Anonymous Coward 1 minute ago

No Comment Entered

255 comments

Well duhhhh. (5, Funny)

pushf popf (741049) | more than 6 years ago | (#19958527)

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

Quick, someone alert Bill Gates!

Re:Well duhhhh. (1, Interesting)

Anonymous Coward | more than 6 years ago | (#19958685)

well duh yourself... none of the smart minds looking at this, obviously a lot more retarded than you are, thought it was possible to do this for years.

But I guess you have no clue about programming and what dangling pointers really are, and you're just replying cause it's slashdot..

Re:Well duhhhh. (1, Flamebait)

pushf popf (741049) | more than 6 years ago | (#19959123)

This just in:
  • The earth isn't flat
  • Fire is hot
  • Poorly written software is exploitable
I've been writing software since "high level language" meant that the assembler understood named labels. Poorly written software had exploitable pointers back then too.

This is just as newsworthy as the discovery that bears crap in the woods.

Re:Well duhhhh. (1, Informative)

Anonymous Coward | more than 6 years ago | (#19959417)

Nobody said it couldn't be exploited before this. It's been known for quite a while that this is an exploitable problem. The point is that it can now be predictably exploited.

If you actually knew what you were talking about, however, I wouldn't have had to tell you that.

does anyone know (-1, Troll)

Anonymous Coward | more than 6 years ago | (#19958537)

why slashdot sucks so much?

the fucked up moderation system.

fuck you all. this website fails.

That's nice and everything but.... (1, Interesting)

Anonymous Coward | more than 6 years ago | (#19958547)

...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 to do this with generic dangling pointers and run our own shell code."

OK, you load the code into memory with the dangling pointer, now, how to you get the instruction pointer to go and execute said code?

Re:That's nice and everything but.... (5, Insightful)

Wavicle (181176) | more than 6 years ago | (#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.

Re:That's nice and everything but.... (4, Insightful)

mark-t (151149) | more than 6 years ago | (#19958995)

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:That's nice and everything but.... (4, Informative)

TheRaven64 (641858) | more than 6 years ago | (#19959163)

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.

SOS? (1)

wsanders (114993) | more than 6 years ago | (#19959023)

And this is somehow a newly discovered hitherto unknown class of exploit?

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

Not that there's any thing wrong with that! (Except that maybe there is a kit now for diddling the danglers.)

Re:SOS? (2, Informative)

quanticle (843097) | more than 6 years ago | (#19959603)

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 [wikipedia.org] 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 [wikipedia.org] 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.

Re:That's nice and everything but.... (1)

jgrahn (181062) | more than 6 years ago | (#19959381)

Presumably what they have here is a dangling pointer to a function, which they can get IIS to then call.

I doubt it. 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.

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.

"Changing the value of the dangling pointer" doesn't make sense -- the whole point of using the name "dangling pointer" is to imply that the program (a) has a pointer to freed memory (heap or stack) and (b) is buggy, i.e. can be tricked into dereferencing it. If the pointer can be changed by the attacker, it doesn't have to be dangling to be vulnerable.

One good guess is they're talking about C++ and dangling pointers to objects with vtables -- if you can overwrite that memory with something interesting, you own the program counter.

Re:That's nice and everything but.... (2, Insightful)

Wavicle (181176) | more than 6 years ago | (#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.

Re:That's nice and everything but.... (0)

Anonymous Coward | more than 6 years ago | (#19959011)

sudo do_bad_things

All the trouble in this world.. (4, Funny)

WarwickRyan (780794) | more than 6 years ago | (#19958553)

..is down to dangly bits.

Re:All the trouble in this world.. (2, Funny)

Herkum01 (592704) | more than 6 years ago | (#19958649)

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

Re:All the trouble in this world.. (1)

reddburn (1109121) | more than 6 years ago | (#19959699)

Not to mention making it harder to catch said dangly bits in a zipper... You may all wince and turn from the screen.

Has Apache fixed it? (1)

Anonymous Coward | more than 6 years ago | (#19958567)

Microsoft seems to have fixed it in IIS and pushed the patch out already. I wonder how many of these Apache has exposed...?

Re:Has Apache fixed it? (1)

WhiplashII (542766) | more than 6 years ago | (#19958823)

Since it was previously considered a "quality issue" but not a security one, I would expect that Apache fixed these errors long ago. At Microsoft, a quality issue is an unaddressed issue - crashes were seen as "avoid when convenient" instead of as a failing. To open source programmers, however, their own pay is kudos on clean code - so they fix things that aren't technically even errors, but instead are quality issues...

Not an Apache issue. (3, Informative)

Ayanami Rei (621112) | more than 6 years ago | (#19959611)

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.

I'm telling my mother! (4, Funny)

east coast (590680) | more than 6 years ago | (#19958577)

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

Re:I'm telling my mother! (-1, Flamebait)

Anonymous Coward | more than 6 years ago | (#19958803)

way to go retard..

filler filler filler its been 30 seconds ok bye

Dangling Prepositions? (-1, Offtopic)

Anonymous Coward | more than 6 years ago | (#19958619)

It will be interesting to see what else they come up with.

The cure... (5, Funny)

Anonymous Coward | more than 6 years ago | (#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."

Pleasantly surprised! (1)

Gazzonyx (982402) | more than 6 years ago | (#19958643)

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.

Re:Pleasantly surprised! (5, Interesting)

Wavicle (181176) | more than 6 years ago | (#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.

Re:Pleasantly surprised! (3, Insightful)

TheRaven64 (641858) | more than 6 years ago | (#19959233)

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.

Re:Pleasantly surprised! (1)

quanticle (843097) | more than 6 years ago | (#19959747)

And again, that's a code quality issue, much like validating input was for buffer overflows.

Re:Pleasantly surprised! (1, Interesting)

Anonymous Coward | more than 6 years ago | (#19958845)

Destroying a pointer isn't the same as destroying the object-pointed-to.

C++ gives you a lot of choices, and thus lots of ways to shoot yourself in the foot if you don't understand those choices and make the correct ones.

The backwards-compatible C-style "dumb" pointers don't do any reference counting, so there's no way for a heap object to know that it's no longer needed. There are other tools to do this job (auto_ptr and others) if that's what you want and need. And you could add GC to your C++ system if you want, though that still leaves you a window of vulnerability between end-of-life and actual cleanup. (Few heap management libraries zero out freed memory, so pointers inside deallocated objects can still be read; they may or may not point to still-valid objects. Even if these internal pointers are not "dangling", they're still a security hole if you hand them to other malicious code in the same address space.)

Re:Pleasantly surprised! (1)

morgan_greywolf (835522) | more than 6 years ago | (#19958889)

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.


Um, no. AFAIK, C++ has no implicit garbage collection. There are plenty of libraries that do garbage collection [hp.com] ...most are essentially replacements for malloc.

But anyway, this is about dangling pointers -- pointers that point to essentially nothing (really, to some 'random' address), either before or after use, not necessarily pointers that haven't been destroyed.

Re:Pleasantly surprised! (1)

aldousd666 (640240) | more than 6 years ago | (#19959239)

I don't think the poster was implying garbage collection, but rather the implicit calling of destructors, which does happen indeed. But the poster was failing to understand the the issue is with another object referring to the address of one that has been possibly destructed or otherwise become invalid. So you're right, just not addressing the concern of the GP.

wow (-1, Offtopic)

Anonymous Coward | more than 6 years ago | (#19958645)

they've discovered the buffer overflow.

More push toward VM's (1)

jshriverWVU (810740) | more than 6 years ago | (#19958647)

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.

Re:More push toward VM's (3, Insightful)

ThinkingInBinary (899485) | more than 6 years ago | (#19958737)

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.

Re:More push toward VM's (5, Insightful)

19thNervousBreakdown (768619) | more than 6 years ago | (#19958873)

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.

Re:More push toward VM's (1)

BitchKapoor (732880) | more than 6 years ago | (#19959035)

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 everything in the kernel. It's not an all-or-nothing thing: the more bugs you can prevent, the better. Even people who know what they're doing make mistakes from time to time. One of the biggest sources of mistakes is when you combine two different pieces of code that seemed to work correctly on their own, but don't quite realize some of the undocumented subtlties in their behaviors, and thus the two interfere and cause an error.

Re:More push toward VM's (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959081)

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:More push toward VM's (2, Insightful)

BitchKapoor (732880) | more than 6 years ago | (#19959205)

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.

Re:More push toward VM's (1)

DragonWriter (970822) | more than 6 years ago | (#19959545)

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.

Re:More push toward VM's (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959659)

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.

Re:More push toward VM's (1)

someone1234 (830754) | more than 6 years ago | (#19958795)

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 (3, Funny)

tttonyyy (726776) | more than 6 years ago | (#19958653)

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

Finally (4, Funny)

dsanfte (443781) | more than 6 years ago | (#19958661)

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

Re:Finally (2, Insightful)

A beautiful mind (821714) | more than 6 years ago | (#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)

Re:Finally (3, Insightful)

BitchKapoor (732880) | more than 6 years ago | (#19959153)

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.

Re:Finally (1)

Nasarius (593729) | more than 6 years ago | (#19959025)

More like: restating one of the reasons that raw pointers should (almost) never be used. A reason for choosing C++ over C, perhaps.

This is nothing new (0, Offtopic)

erroneus (253617) | more than 6 years ago | (#19958665)

Women have been exploiting dangling pointers for centuries... millennia even! :)

a new pickup line... (3, Funny)

Anonymous Coward | more than 6 years ago | (#19958673)

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

Known since 2005 (4, Interesting)

drspliff (652992) | more than 6 years ago | (#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?

Re:Known since 2005 (4, Insightful)

nagora (177841) | more than 6 years ago | (#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:Known since 2005 (2, Interesting)

jimicus (737525) | more than 6 years ago | (#19958875)

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.

Why are we still dealing with this? (4, Insightful)

19thNervousBreakdown (768619) | more than 6 years ago | (#19958779)

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?

Re:Why are we still dealing with this? (1)

j00r0m4nc3r (959816) | more than 6 years ago | (#19958879)

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.

Re:Why are we still dealing with this? (5, Insightful)

PetriBORG (518266) | more than 6 years ago | (#19958939)

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:Why are we still dealing with this? (4, Insightful)

BitchKapoor (732880) | more than 6 years ago | (#19958977)

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.

Re:Why are we still dealing with this? (4, Funny)

Red Flayer (890720) | more than 6 years ago | (#19958981)

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

Re:Why are we still dealing with this? (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959191)

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

Re:Why are we still dealing with this? (1, Insightful)

Anonymous Coward | more than 6 years ago | (#19959339)

That's actually a semantic error, not a syntactic one.

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

Re:Why are we still dealing with this? (3, Informative)

Red Flayer (890720) | more than 6 years ago | (#19959723)

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.

Re:Why are we still dealing with this? (1)

Coward Anonymous (110649) | more than 6 years ago | (#19959379)

What's the biggest project you've worked on?

Re:Why are we still dealing with this? (4, Informative)

140Mandak262Jamuna (970587) | more than 6 years ago | (#19959423)

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:Why are we still dealing with this? (4, Funny)

slackmaster2000 (820067) | more than 6 years ago | (#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.

Re:Why are we still dealing with this? (0)

Anonymous Coward | more than 6 years ago | (#19959607)

> I dunno. I manage to write C++ and never overflow a buffer,

As far as you know. If your software was as popular as Linux or MSIE, I'd bet many problems would be found.

Re:Why are we still dealing with this? (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959807)

Yeah, there was a little hyperbole there, but I was trying to make a point. Although, to be fair, I still run all of my code through Valgrind and I've only caught an error like that twice in about 8 years. Once was C++ type demangling to make an error message human-readable, which as I recall was really poorly documented as to whether you or the library freed the memory, and the other was interfacing with getopt_long(), I tried to free argv. Whoops. I do have bugs, but it's extremely rare that it's of that type. I view a programmer making that type of a mistake about the same as a person trying to walk across the room and falling on his face. Which I've done, twice.

Re:Why are we still dealing with this? (1)

RAMMS+EIN (578166) | more than 6 years ago | (#19959783)

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

Re:Why are we still dealing with this? (1)

Chyeld (713439) | more than 6 years ago | (#19959791)

Probably because their not on their 20th nervous breakdown. (it's a joke, but there is a point to it.)

what a headache (2, Informative)

circletimessquare (444983) | more than 6 years ago | (#19958793)

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

Re:what a headache (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19958967)

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?

Re:what a headache (0)

Anonymous Coward | more than 6 years ago | (#19959393)

No it is not engineering because companies like the one I work for hire BCIS and MIS people and have them code. They only programming class they took was VB.net. It gets them a job and then they kiss ass and they become the CS student's boss. It is sad, I tried to tell my boss they have a memory leak in there legacy application and she said "Huh?" Welcome to the world where you just have to know how to make an HTML page in FrontPage and know how to copy and paste some JavaScript and you get a job writing a 20 million dollar application.

FUD! We're important! (2, Insightful)

kwerle (39371) | more than 6 years ago | (#19958861)

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)

NULL those pointers, folks (3, Interesting)

steveha (103154) | more than 6 years ago | (#19958985)

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

Re:NULL those pointers, folks (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959065)

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.

Re:NULL those pointers, folks (3, Insightful)

cerelib (903469) | more than 6 years ago | (#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.

Re:NULL those pointers, folks (0)

Anonymous Coward | more than 6 years ago | (#19959563)

This protects against mixing up the assignment (=) and the equality test (==). With the lvalue on the right, this mixing up leads to a syntax error. With the lvalue to the left, you still have syntactically correct code (although the compiler will likely emit a warning).

Re:NULL those pointers, folks (3, Insightful)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959581)

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.

Re:NULL those pointers, folks (3, Informative)

BitchKapoor (732880) | more than 6 years ago | (#19959085)

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.

Re:NULL those pointers, folks (1)

19thNervousBreakdown (768619) | more than 6 years ago | (#19959347)

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

Re:NULL those pointers, folks (3, Informative)

steveha (103154) | more than 6 years ago | (#19959619)

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:NULL those pointers, folks (0)

Anonymous Coward | more than 6 years ago | (#19959583)

7.20.3.2 The free function Synopsis [#1] #include void free(void *ptr); Description [#2] The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined. Returns [#3] The free function returns no value.
free(NULL); is NOP. The only useful thing your function does is make the pointer that is free'd NULL, but this alone does not prevent a double free. delete is similar:

The value of the first argument supplied to one of the deallocation functions provided in the standard library may be a null pointer value; if so, the call to the deallocation function has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(size_t) or operator new(size_t, const std::nothrow_t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](size_t) or operator new[](size_t, const std::nothrow_t&) in the standard library.

Re:NULL those pointers, folks (0)

Anonymous Coward | more than 6 years ago | (#19959701)

7.20.3.2  The free function

       Synopsis

       [#1]

               #include <stdlib.h>
               void free(void *ptr);

       Description

       [#2] The free function causes the space pointed to by ptr to
       be  deallocated,  that  is,  made  available   for   further
       allocation.   If  ptr  is  a null pointer, no action occurs.
       Otherwise, if the argument does not match a pointer  earlier
       returned  by  the calloc, malloc, or realloc function, or if
       the space has been deallocated by a call to free or realloc,
       the behavior is undefined.

       Returns

       [#3] The free function returns no value.

and

-3- The value of the first argument supplied to one of the deallocation functions provided in the standard library may be a null pointer value; if so, the call to the deallocation function has no effect. Otherwise, the value supplied to operator delete(void*) in the standard library shall be one of the values returned by a previous invocation of either operator new(size_t) or operator new(size_t, const std::nothrow_t&) in the standard library, and the value supplied to operator delete[](void*) in the standard library shall be one of the values returned by a previous invocation of either operator new[](size_t) or operator new[](size_t, const std::nothrow_t&) in the standard library.

Re:NULL those pointers, folks (0)

Anonymous Coward | more than 6 years ago | (#19959741)

The only useful thing [FreeFoo()] does is make the pointer that is free'd NULL, but this alone does not prevent a double free.

PFOO pfoo = PfooNew(args);
free(pfoo); /* frees the FOO */
free(pfoo); /* undefined behavior (probably a crash) */

PFOO pfoo = PfooNew(args);
FreeFoo(&pfoo); /* frees the FOO and sets pfoo to NULL */
FreeFoo(&pfoo); /* does not crash, and asserts to warn you */

I would claim that FreeFoo() prevented a double-free error in the above code.

PFOO pfoo = PfooNew(args);
PFOO pfooTemp = pfoo;

FreeFoo(&pfoo);
FreeFoo(&pfooTemp); /* whoops, double free */

Okay, in this code, FreeFoo() wasn't enough to save the developer from screwing up. That doesn't make the trick useless.

Re:NULL those pointers, folks (2, Insightful)

jgrahn (181062) | more than 6 years ago | (#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.)

Out of curiosity - who uses C/C++ for web (1)

lena_10326 (1100441) | more than 6 years ago | (#19959061)

....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 almost as fast as a bare C server. Debating 1,000 connections per second versus 10,000 connections per second is a bit moot when your system isn't topping 300 req/second, even at system peak.

So. Does anyone have a reason for C/C++ web code that's not based on performance? Say, a library wrapper for accessing a legacy data source for which there's no scripted library?

Re:Out of curiosity - who uses C/C++ for web (1)

six (1673) | more than 6 years ago | (#19959211)

Say, a library wrapper for accessing a legacy data source for which there's no scripted library?

I think this is what the ffi [php.net] extension for PHP is all about

What is this? (1)

SloWave (52801) | more than 6 years ago | (#19959235)

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?

Re:What is this? - can we make it jump to code? (1)

DogFacedJo (949100) | more than 6 years ago | (#19959769)

If a dangling pointer is followed into 'random memory' what are the odds it'll hit exploit code? Sometimes very low...
    Oftentimes, however, the original value was off of the heap, so if one can make the app allocate a whole bunch of memory there might be even odds that the pointer will now point into that memory. If that memory consists of a huge header which can be *entered at any point* (eg: big pile of nops) and forwards execution along to the end where one has the exploit code proper... then you have an exploit.

    See some other post about how to get from an ordinary pointer to an executable one (eg: a function pointer)... how rare are function pointers?

"Security experts" that aren't (4, Insightful)

Schraegstrichpunkt (931443) | more than 6 years ago | (#19959629)

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.

A big "if" (1)

SkyFalling (1115231) | more than 6 years ago | (#19959651)

The article is a bit thin on the details of how the exploit works. Without some kind of explanation, I'm skeptical of the claim that this works for "any application in which there is a dangling pointer." In particular, note the quote that "[t]he long and short of it is, if you can determine the value of the pointer, it's game over." Okay, but I'm not in the habit of exposing pointer values to users, so if a user-visible pointer value is required for the exploit, that significantly reduces the set of apps to which this attack applies. The apparent overstatement degrades the overall credibility of the related claims. Also, I'm really curious why on earth it would matter that the pointer is dangling. A dangling pointer is a pointer that points to a resource that no longer exists -- and, therefore, to garbage memory. I'm assuming the attack involves writing arbitrary code to that garbage memory. The question is, why would such an attack rely on the memory being garbage, as opposed to a valid resource? If we're overwriting it anyway, why does it matter? Perhaps what really happens is that when you crash due to a dangling pointer, the resulting dialogue shows the pointer value, and this tells the attacker which location to overwrite for the next time. If that's the case, it strikes me as being just as obvious as, say, buffer overflow, and that dangling pointers are rather incidental. I guess we'll have to await the details to determine if there really is meat here, a legitimate new class of attacks, or just overstatement of something not at all new an exciting.

AAARGH! (1)

RAMMS+EIN (578166) | more than 6 years ago | (#19959667)

<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".
Load More Comments
Slashdot Account

Need an Account?

Forgot your password?

Don't worry, we never post anything without your permission.

Submission Text Formatting Tips

We support a small subset of HTML, namely these tags:

  • b
  • i
  • p
  • br
  • a
  • ol
  • ul
  • li
  • dl
  • dt
  • dd
  • em
  • strong
  • tt
  • blockquote
  • div
  • quote
  • ecode

"ecode" can be used for code snippets, for example:

<ecode>    while(1) { do_something(); } </ecode>
Sign up for Slashdot Newsletters
Create a Slashdot Account

Loading...