Bugtraq mailing list archives

SLMail 3.0.2421 Stack Overflow...


From: aleph1 () DFW NET (Aleph One)
Date: Thu, 9 Jul 1998 11:54:17 -0500


---------- Forwarded message ----------
Date: Wed, 8 Jul 1998 17:32:02 PDT
From: Ezekial Morrow <paceflow () HOTMAIL COM>
To: NTBUGTRAQ () LISTSERV NTBUGTRAQ COM
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



Current thread: