Supermicro IPMI Exploitation: CVE-2019-19642
Software & Hardware Versions Exploited in POC
Hardware: Motherboard model number: X8STi-F Software: IPMI FW Version: 2.06, BIOS Version: 02.68
Vulnerability Description
The Virtual Media feature of the web based IPMI contains an OS Command Injection issue, allowing attackers to execute arbitrary commands on the victim system’s firmware. Attackers exploiting this issue are able to install backdoors or pivot into a network and execute further attacks within the victim network.
This type of issue is classified as CWE-78, improper Neutralization of Special Elements used in an OS Command.
Vulnerability Exploitation
The vulnerability exists in /rpc/setvmdrive.asp. When sending an authenticated POST request to this URL, the POST parameters ShareHost and ShareName can injected with bash commands. To attain execution of the injected commands, “backticks” also referred to as “backquotes” are used. Backticks are special characters within bash that are used for Command Substitution. Essentially, command substitution within an exploitation context, executes attacker supplied bash command within an application’s bash command. Here’s how this works with an example command.
ping 8.8.8.8
This would execute ping as you’d normally expect
ping `cat /etc/passwd`
The ping command would fail, but bash would execute cat /etc/passwd in addition to ping.
Initial Testing
When testing for this vulnerability initially with Burp, the sleep command was used. You can see in this screenshot that the request took 6 seconds, proving that the fields are indeed injectable.

In an attempt to further determine if this issue was exploitable, the nslookup command was used to send a dns request to an external system as an out-of-band test. You can see here that a dns request was received from the IPMI ip address (192.168.0.3).

Getting Shell Output
To receive shell output of the commands I was running, had to get creative. This SetVMDrive function that’s being called, mounts a cifs (a.k.a SMB) drive to either /conf/mnt/sda1 or /conf/mnt/sda2 on the firmware’s underlying BusyBox OS. This cifs mount is intended to be used as a location to store .iso or .img files for the server to boot from. In this case, I was able to abuse it and have the system write files containing shell output on a remote smb share, this gives us full output of the commands.
First, I had to mount my local system to the IPMI firmware. We can see that it was successfully mounted.


So now I can redirect shell output to our CIFS share, note that the >> operators are redirecting output. In this first screenshot, ifconfig was executed, then we can see we’re running as root with ps.

Persistiance
I also have the ability to insert persistence mechanisms or backdoors, since there’s a read/write FS mounted on /conf and write access to a cron instance.

Firmware Reverse Engineering
To find the source of the vulnerability, first I took a look at the actual .asp file being called.
This file is located at /usr/local/www/rpc/setvmdrive.asp on the busy box os. Here’s the contents:
<% WEBIFC_IPMICMD("libifc_ipmi.so.1.0","WEBIFC_IPMICMD_SetVMDrive", "param"); %>
<% hapiRPCRespFn("RPC", "sendResponse"); %>
This ASP file is calling a function called WEBIFC_IPMICMD_SETVMDrive in a shared library called libifc_ipmi.so.1.0. Digging further into this shared library using Ghidra, I was able to decompile the function and find the source of the vulnerability. Here’s a snippet of the decompiled code showing the issue.
local_280[0] = websGetVarInt(uParm3,"VMDrive",local_280);
local_284 = websGetVarInt(uParm3,"ImageType",&local_284);
__src_03 = (char *)websGetVarWrap(uParm3,"ShareHost",0);
__src = (char *)websGetVarWrap(uParm3,"ShareName",0);
snprintf(acStack480,200,
"mount -t cifs -o user=\"%s\",workgroup=\"%s\",pass=\"%s\" //%s/%s /conf/mnt/sda%d",
&local_278,&local_250,__src_02,__src_03,__src,local_280[0] + 1);
}
iVar2 = system(acStack480);
What we see in this code snippet is that user supplied values __src_03”(ShareHost) and __src”(ShareName) are stored in an array, then the array is executed via system(). There’s no input validation, or neutralizing of dangerous special characters. Note that this is was decompiled from a compiled .so file, so variable names and other minor things could be different from source, but functionally and programatically the same.
Contact with SuperMicro
These details were sent to SuperMicro and they have released a patch to the firmware in version 3.08. This issue has been assigned CVE-2019-19642.