Dolibarr ERP CRM is an open-source software package for companies of any size, foundations or freelancers. It contains
various functions for Enterprise Resource Planning and Customer Relationship Management, but also other functions for
various activities [1].
SmartTECS Cyber Security GmbH discovered that the Dolibarr web application is vulnerable to a
reflected cross-site scripting vulnerability for authenticated users.
One of the defence mechanisms used by Dolibarr against XSS can be found inhtcdocs/main.inc.php
. The
function testSqlAndScriptInject
performs several checks to prevent XSS attacks. However, the onbounce
JavaScript event is not
blacklisted (
see details Bypassing-filter
).
The vulnerability can be found in https://<url>/compta/paiement/card.php?action=valide&facid=...
during the validation
process of a payment. The vulnerable code is located in line 291 of htdocs/compta/paiement/card.php
:
Source: '$_GET' @ 'htdocs/compta/paiement/card.php:291'
Propagator : '$facid' @ 'htdocs/compta/paiement/card.php:291'
Sink: 'print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id.'&facid='.$facid, $langs->trans("ValidatePayment"), $langs->trans("ConfirmValidatePayment"), 'confirm_validate', '', 0, 2);' @ 'htdocs/compta/paiement/card.php:292'
// Confirmation of payment validation
if ($action == 'valide') {
$facid = $_GET['facid'];
print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id.'&facid='.$facid, $langs->trans("ValidatePayment"), $langs->trans("ConfirmValidatePayment"), 'confirm_validate', '', 0, 2);
}
An authenticated user can use the facid
parameter to injection malicious JavaScript code. By using the marquee
element an
attacker could inject malicious JavaScript code using the onbounce
event, such as:
12345--><marquee behavior=alternate loop=2 onbounce=alert(document.location)>XSS</marquee><!--`
Then, when a user clicks on the link, the JavaScript code is executed after the bounce which can take a few seconds.
If you try to use a common known payload, an error message will be displayed:
To understand how the filter works, let’s have a look in the Source Code function testSqlAndScriptInject
which can be found in
htcdocs/main.inc.php
. The following code snippet is relevant:
An interesting observation is that regular expressions are used to try to intercept all possible events that could be used for a payload. With this knowledge, it is possible to search for a “forgotten” event that is not intercepted. The PortSwigger Cross-site scripting (XSS) cheat sheet [3] is a great resource for identifying this type of WAF or filter bypass.
In this case, it is the JavaScript onbounce
event for the deprecated html tag marquee
that is missing from the filter function.
However, the payload suggested by PortSwigger does not trigger the expected payload. As the Mozilla developer documentation
shows that the event will only fire if the behaviour=alternate
attribute is set [4].
Now the basic payload described above can be crafted. A real attacker would probably use thescrollamount
attribute,
which influences the speed, as it may take a while for the element to bounce on wide screens, but the payload should be
executed immediately.
In general, it is not a good idea to solve this topic of sanitizing user input using regular expressions. Crafting effective regular expressions for sanitization can be complex and error-prone. XSS attacks can utilize various encoding techniques and HTML attributes, making it challenging to cover all possible attack vectors with regular expressions alone. Attackers constantly develop new techniques, and your solution might not keep up with the evolving threat landscape. Instead, it is recommended to use established libraries and frameworks that provide robust XSS protection mechanisms like (PHP AntiXSS, HTML Purifier or htmLawed).
5.1 / Medium (CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N)
https://<url>/compta/paiement/card.php?action=valide&facid=12345--><marquee behavior=alternate loop=2 onbounce=alert(document.location)>XSS</marquee><!--
The vendor has fixed this in branch v19 for future v19.0.2 of Dolibarr [5].
// Confirmation of payment validation
if ($action == 'valide') {
$facid = GETPOSTINT('facid', 3);
print $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id.'&facid='.$facid, $langs->trans("ValidatePayment"), $langs->trans("ConfirmValidatePayment"), 'confirm_validate', '', 0, 2);
}
2024-03-18: Vulnerability found
2024-03-28: Vendor contacted
2024-03-28: Vendor confirmed vulnerability
2024-04-05: CVE ID request
2024-03-04: CVE ID received
[1] Dolibarr Homepage, Dolibarr, Available at https://www.dolibarr.org/
[2] CVE Record, MITRE Corporation, Available at https://www.cve.org/CVERecord?id=CVE-2024-34051
[3] Cross-site scripting (XSS) cheat sheet, PortSwigger, Available at https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
[4] marquee: The Marquee element, Mozilla, Available at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee#onbounce
[5] Dolibarr fixed card.php, Dolibarr, Available at https://github.com/Dolibarr/dolibarr/blob/develop/htdocs/compta/paiement/card.php