SuperMicro IPMI Exploitation

Software & Hardware Versions Exploited in POC

This vulnerability is now known as CVE-2019-19642

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 ('OS Command Injection').


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.

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 my local Kali Linux system. You can see here that a dns request was received from the IPMI ip address (192.168.0.3).




To receive shell output of the commands I was running, I 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 in 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 redirect shell output to a file on this cifs mount located on my Kali Linux system where I was able to see the output of commands I was running.
First, I had to mount my kali 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.



Using the ps command, we can see that I’m running as root.



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"); %>


So, 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 with a reverse engineering tool, 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 expressed some interest, but not enough to patch or disclose the issue.

Conclusion

Thanks for reading! I haven’t been able to determine if any other hardware platforms are affected, as this is the only SuperMicro system I own. Personally, I think this issue could be used to install sneaky backdoors in systems or for lateral movement.

Popular posts from this blog

OSSEC Privilege Escalation via Directory Traversal