Date: Wed, 8 Jul 1998 17:32:02 PDT From: Ezekial Morrow Subject: SLMail 3.0.2421 Stack Overflow... Product: SLMail 3.0.2421 from Seattle Lab. Vulnerability: Stack overflow - Remote execution of code. Jeremy Kothe (paceflow@hotmail.com) If the "mail from" field exceeds 256 bytes, it will pass through the receive process without being trimmed... When the mail dispatcher picks up the mail file to process, it copies it into a stack buffer of only 256 bytes, overwriting the function return address and normally halting the SLMail server. The DOS attack is simple - simply send an e-mail with "mail from" > 256 bytes. To exploit the attack to remotely execute code is difficult but NOT impossible. The main difficulty is that the string which overflows the stack (the "mail from" name) can contain only valid email address characters. But don't think that makes it impossible... Introduction Stack overflows under xnix are usually a simple affair - create a shell and pipe it to the attacker. Under Windows 95 or Windows NT, however, the task is a little more complex. If you are not familiar with basic win32 stack overflow methods, see dildog's excellent (although 40 iq points too dumb for most of us:}) article at http:\\www.cultdeadcow, as well as his contributions at http:\\www.l0pht.com. Tools Microsoft's under-rated (though limited) WinDbg to debug and examine the fault. Borland's Turbo Assembler and DataRescue's IDA (disassembler) for converting my code into data bytes (no, sorry, I refuse to remember that 0x50 is push eax... oh shit). Borland Delphi - my 3gl of choice for the Windows environment to create and send the e-mail. Any ip-capable platform could of course be used here. Gaining Control The idea behind ANY overflow execution exploit is to leverage a bug or crash to execute data. To do anything, we must first "snag the EIP". To do this, we must examine the environment produced by the initial crash, find somewhere a pointer to our data, and then somhow get it into the eip register... So let's take a look at the environment created when SLMail overflows... Fire up SLMail.exe (it's a service, so use "net start slmail" or the control panel), then start WinDbg and Attach (F6) to the SLMail process. Press F5 to continue execution... Now we create a test program to send a buffer of 1600-odd 0x61 ("a")'s as the email from address. Running this program, our e-mail is accepted and placed, as a file, into SLMail's "In" subdirectory. SLMail.exe then picks up this file and bang... WinDbg reports our first-chance-exception at 0x42264f. 0042263C mov ecx, [esp+114h+arg_0] 00422643 mov edx, [esp+114h+arg_4] 0042264A mov eax, [esp+114h+var_104] 0042264E pop edi 0042264F ==> exception mov [ecx], esi 00422651 mov [edx], eax 00422653 mov eax, ebp 00422655 pop esi 00422656 pop ebp 00422657 pop ebx 00422658 add esp, 104h 0042265E retn The memory address which is being written to here happens to be 0x61616161, which we see four lines above as being the procedure's first argument on the stack... Looking at the registers, we find that the stack area has been well and truly overwritten by our test data, and that several registers (esp, esi, edi) are pointing to areas within this data area. And if we can stop the exception at 0x42264f, and the next one at 0x422651, then the retn will return to 0x61616161, or whatever else we choose to feed it... To stop the crash, we need to find an address which is writable, and place two copies of it into our buffer in the appropriate place... This would be no real problem except for our main limitation, the alphanumeric-only content of our buffer allows us only 1/1024 of the address space... So we search and search... Nothing in the main program, so one-by-one we check the dlls used. Now, this is where the issue of platform-dependency comes along. If we use an address in a dll, we are binding the exploit to that version of the dll. Any other versions would crash... Luckily, the proliferation of NT 4.0 sp3 platforms provide a number of large dlls which are fairly constant... (ie: user32.dll, kernel32.dll). It's worth remembering that NT server and workstation binaries are identical, so even by targeting only this one platform, an attacker could probable achieve a > 70% success rate on a random basis. So eventually, I found an address in a dll data segment which was valid for us to use, and plugged it in. Now we're past the crash... Returning to the stack via Microsoftware... Normally, at this point, you could open up the main executable in IDA, turn on showing of op-codes, then do a string search for a " 54 " (the op-code for push esp). Ideally, what you're looking for is: push esp retn Of course this would not usually be done, but by seaching for " 54 ", you can almost always find something like: add esp, 54h retn Which is really the same thing! Just ignore the "add esp, " and voila. Again, this is made enormously difficult because of the 1/1024 limitation... And in this case, dig as I might, I couldn't find anything at a valid address... The closest thing I could use were a few bits like this: push esp (actually an add esp, 54h) pop eax/ebx pop edi ... retn Now all this does is to get esp into eax. Doesnt seem like much until you realise thats it's relatively common to do a "call eax" or "call ebx". So, we go and find ourselves a "call eax/ebx" statement again with a valid (alphanumeric) address. We find a "call ebx" which we can use, so we go back and find a variant of the above code snippet which moves our esp into ebx. Positioning these two addresses at the correct position in the buffer can be tricky, but eventually we end up returning to what was originally our stack. The first stage of the attack is over, and were it not for the alphanumeric limitations, the battle would be over. Executing Text We have control of the eip... cheer, rest, think. What can we put in our buffer to execute? Not bloody much. Every byte in our buffer MUST be valid alphanumeric. I wouldn't have come this far without a plan, though. My idea is to use what small instruction set we DO have to dynamically CREATE a more flexible piece of code. Checking the instructions available to us in the character set we have, I find that we have all of the "push"es and most of the "pop"s. Along with, luckily, the "-" character, which turns into a "sub eax, ...", I came up with a plan... The initial code would PUSH the program onto the stack, then execute it from there. The first trick is to push bytes which cannot be in our buffer, I came up with the following: push xxxxxxxxh pop eax sub eax, xxxxxxxxh ... sub eax, xxxxxxxxh push eax Effectively, this means that for each DWORD of the target program, we need to calculate a series of valid DWORDs which subtract from one-another to produce the target DWORD... Sounds tough, but it turns out that a bit of brute force solves this one easily. I wrote a fairly simple program () which calculated these numbers and produced code for me to cut and paste. After we've pushed this program onto the stack however, we need then to jump or call to it. Unfortunately our limited instruction set has only short jumps, which limits our range so much we'd have to chain them. The initial location of the stack pointer, and therefore the pushed program, is just above our current location ( where we are pushing the program ). So, instead of chaining short upwards jumps which would be hell to position and maintain, I inserted a series of "popad" instructions to move the stack pointer down, over and past the push code, allowing only enough room for the target program. The program is then pushed onto the stack and voila, no jump or call needed. We have created the program in front of our eip and we naturally execute into it. Tricky, but by leaving a bit of room at the end of the "push"ing routing filled with harmless "inc esi" instructions, it works fine. So, by using about 6-16 bytes per DWORD, we can create and run a program. At this rate, we would rapidly run out of room in our buffer to do anything. So, we add another trick. The program we produce is a small decompression routine. Using a simple nibble to byte compression routine to encrypt our main program and place it elsewhere in the buffer. This allows a 2 DWORD to 1 DWORD compression ratio, and a larger main program. The decompression routine is simple enough: ; assume edx points to source area mov esi, esp add esi, 122 ; source from esp... ; get length of code... xor ecx, ecx mov cx, word ptr [esi] add esi, 2 sub cx, 6161h mov bx, cx shr cx, 4 or cl, bl ; decode code... decode: mov eax, [esi] add esi, 4 sub eax, 61616161h mov ebx, eax shr eax, 4 or al, bl mov ebx, eax shr eax, 4 mov al, bl ror eax, 0ch shr al, 4 rol eax, 0ch push ax loop decode call esp Where Do We Want To Go Today? Game over, We can run ANY code we want at this point. I have included a full exploit program which simply create a file in the current called "md9.exe" containing the text string "SLMail contains a stack overflow", but it could just as easily be downloading a complete .exe using sockets, the inet32 api, or other means. This program could in turn re-start the SLMail service, remove any offensive log entries etc... Conclusion Seattle Lab have played down response to concerns over overflows in the VRFY argument of versions 2.5 and 2.6 of SLMail. They said that the security risk was minimal. Too hard to exploit, they said. As it turns out, the overflows in 2.5&6 are THE SIMPLEST POSSIBLE KIND. They are direct overflows with no major limitations on character set. So you can skip all the de-compression and pushing-of-programs, and locating valid addresses now means only avoiding 0's... I wrote this exploit in less than two days. Thats from the time I downloaded the evaluation copy of SLMail to the time I had arbitrary code executing on it. Now I'm not a bad guy, and I'm not paid to do this. Imagine what even governments around the world would be able to do with even a minimal "tiger team". The real message here is that this is not an isolated flaw. Buffer overflows of one kind or another are notoriously common even today on the more secure xnix platforms, and even more common on Windows Services written by programmers who do not realise or understand how serious these problems are. Recent posting to security sites reveal buffer overflows in COMMON products such as WS-FTP, SLMail, MDaemon, sendmail!!! and others. Any serious group of hackers would no doubt be yawning over my techniques here. They would have pre-fabricated routines to slot into place for various kinds of common overflows, allowing any server to be attacked potentially via any service it offers. Of course the entire DOMAIN of the attacked machine is subverted as well, so machines connected via LANs and even WAN/IP are also vulnerable, even if they don't run any vulnerable services. WAKE UP PLEASE!!! The US Congress is deliberating legislation which would make it illegal for the sites which distribute information like this illegal. The effect of this would be that the developers ( in this case Seattle Lab ) would NOT EVEN KNOW the problem existed... Whilst ANY serious hacker would have found and exploited it months ago... As an example, it is not hard to write an overflow test program for a given protocol - be it SMTP, FTP, etc. Simply by running these test suites over each new server as it is released, the hackers identify vulnerabilities quickly and painlessly, then exploit. The large number of Server providers, and the LACK OF EDUCATION amongst the authors of these programs remains a huge security risk to business and privacy on the internet. The legislation assumes that what I am doing here is providing a "how-to" manual for would be "bedroom teen-superhackers" (script kiddies). Instead, what I am doing is SHOWING WHAT OTHERS ALREADY KNOW. No teenager from his bedroom will be able to use this technique to do any real damage. If he or she were to try, they would be logged and caught without too much trouble. The government teams and whoever else has a professional interest however, ALREADY KNOW IT. I hope Seattle Lab and others will read and understand, then STOP using the "It would be too hard to exploit" excuse. Jeremy Kothe (paceflow@hotmail.com) P.S. Seattle Lab has been informed... No response yet. ______________________________________________________ Get Your Private, Free Email at http://www.hotmail.com