Under Lab Conditions, Mark Dowd Re-creates 1997
Matasano Team | March 24th, 2006 | Filed Under: Disclosure, New Findings
This is as far as I’d gotten before I gave up, hit “up up down down left right left right B A start” and asked some friends on AIM how the Sendmail signal problem is exploitable.
- Clue 1: jack@rapturesecurity posted a writeup, which
gives us:
- In data-mode, while reading headers, Sendmail will log (calling sm_syslog()) when a line exceeds 32k.
- While reading from a client, Sendmail will receive SIGALRM if no data is received within an interval. Sendmail timers work like C++ exceptions, unwinding to a guard clause before the timed event.
- So, putting (1) and (2) together: you can get the sm_syslog() and the timeout to happen at the same time by sending the “last” byte of the header exactly when you expect the data timeout to fire.
- Jack says Sendmail then crashes in sm_syslog.
- Clue 2: Eric Allman posted to Bugtraq:
It is an extremely subtle problem that involves making an alarm signal occur in a very small section of code as the result of a multi-minute timeout. The signal causes a longjmp that can leave a piece of code in an inconsistent state.
The rest of the details of the attack have probably already come out by the time you’re reading this post, or will very soon. Regardless of what Allman says, this is not a subtle bug. Sendmail timers work like exceptions.
Most of Allman’s Bugtraq message is actually useful (something about this advisory seems to have scrambled Gadi Evron’s brain). But it is Eric Allman writing about Sendmail security, and so we get this gem:
ISS explained it to us and told us that they had managed to craft an exploit in their lab, but frankly we don’t see how it can be practical. This literally requires nanosecond precision in the millisecond world of networking.
Yeah, because what’s happening here is that ISS has a state-of-the-art “lab” equipped with supercomputers and a time machine, not that Mark Dowd knows how to set a timer, multiply by 100,000, or write a loop. Then again, since SIGALRM-plus-longjmp has been a Sendmail idiom since the early ’90s (despite being literally the man-page example of what not to do with longjmp), maybe it just seems that way to Allman.
For those of you who missed the temp-file-race rennaissance of 1994: it is usually hard to trigger a race condition reliably. That’s why you attempt them over and over again until they work.


blog
April 8th, 2006 11:13 pmIt wouldn’t be a race if you won everytime, would it
Dr. Strangelove | 03.27.06 - 10:46 am | #
Keep checking the rapture link for updates. When we get a more reliable method of exploitation, I’ll post it to the Dyad page in the advisory section.
Robert
Robert E. Lee | Homepage | 03.28.06 - 5:36 am | #
fingerout
June 27th, 2006 11:57 amAnything new about this issue? I’m doing research on this and it seems that the only possible way of making this race occur is sleeping on sm_io_getc in switch(mstate) case MS_HEADER since after sm_io_getc at the beginnig of inner loop (for(;;)) will cause setting CollectProgress to true which results in resetting the timer, so no race (no longjmp call) will occur.
Any thoughts?
fingerout
June 27th, 2006 1:05 pmAfter some more code analysis I think that it is impossible for the signal to be delivered while being in sm_syslog because of headers length -> can’t get there with CollectProgress == false (which is the condition of longjmp occurance), since if we manage to bypass setting CollectProgres to true by going into switch(istate) case IS_DOTCR thus having pbp incremented, we will land in sm_io_getc after which CollectProgres is set to true, because of:
if (c == ‘\r’ && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) {
istate = IS_CR;
continue;
}
since c is set to ‘\r’ in IS_DOTCR and with default settings this bitset() will return false so condition will be met.
The char will be processed and we’ll be back waiting for another one (then CollectProgres = true).
Please correct me if I’m wrong…
fingerout
June 27th, 2006 1:09 pmSo the only possible exploitation vector I see is to be in chompheader() when the signal is delivered.
MODERATOR, PLEASE MAKE THESE 3 COMMENTS ONE ;], THX
fingerout
June 27th, 2006 7:33 pmOr in any other function before this code:
if (CollectTimeout != NULL)
sm_clrevent(CollectTimeout);
Thomas Ptacek
June 27th, 2006 8:03 pmI really want to follow up on this stuff (for what it’s worth, from memory, this is basically a weaponized version of the classic C++ exception handling bug — aborting in the middle of a function, unbeknownst to the code in that function, leaves dangling references. In this case, a dangling referencing into the stack, stored in a function static.)
I’m a bit buried, but I’ll try to get at it later on tonight.
fingerout
June 28th, 2006 8:14 pmAfter a bit cheating (putting sleep in sm_syslog() :P) i managed to exploit the race condiotion and got: Jun 29 02:48:14 fingerout sendmail[10085]: k5T0m3Lv010085: Séˇout waiting for inpTö˙˙˙om fingerout.lambda.furrynet.org during message collect
in syslog. Now comes another part: how to exploit this static pointer overwrite;]. Any ideas?
Thomas Ptacek
June 28th, 2006 8:40 pmI haven’t gotten back to this yet, but, the static pointer can be left in a state where it’s pointing into the stack.
fingerout
June 28th, 2006 8:54 pmCorrect, but how to exploit it ;)?
Thomas Ptacek
June 28th, 2006 8:56 pmLike any other stack overflow?
fingerout
June 28th, 2006 9:34 pmOr heap one, since it’s possible to force sm_syslog making this static pointer = mallocated buffer.
Thomas Ptacek
June 28th, 2006 9:37 pmMy sense of it was, addresses written over stack frames (part of the trick is getting the function to abort leaving a dangling pointer into the stack).
fingerout
July 1st, 2006 2:00 amDONE :]
Thomas Ptacek
July 1st, 2006 10:23 pmCongratulations. How’d you do it?
piscis
December 3rd, 2007 12:19 pmhello~~~dear All~~~~
I am just starting to learn this bug~~~~
I find this issue too. And I get the program sendtest_c from http://www.securityfocus.com/bid/17192/exploit. But I don’t know how to make this become a really expolitation. I think this for months. I feel that I can’t go forward any more~~~~please give me some hint or help~~~~
thanks~~~
Leave a reply