Coordinated Disclosure Timeline
- 2022-04-12: Report sent to maintainers.
- 2022-04-12: Receipt acknowledged.
- 2022-04-13: CVE-2022-29158 assigned.
- 2022-09-02: v18.12.06 with a fix released.
Summary
Apache OFBiz up to version 18.12.05 is vulnerable to Regular Expression Denial of Service (ReDoS) in the way it handles URLs provided by external, unauthenticated users. Specially crafted URLs may cause catastrophic backtracking, taking exponential time to complete.
Product
Apache OFBiz
Tested Version
Details
Issue: Regular Expression Denial of Service (ReDoS) in UtilHttp.java
. (GHSL-2022-025
)
The Apache OFBiz framework uses the following regular expression in the method UtilHttp.extractUrls
to identify URLs being passed as parameters in HTTP requests:
Pattern pattern = Pattern.compile(
"\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)"
+ "(\\w+:\\w+@)?(([-\\w]+\\.)+(com|org|net|gov"
+ "|mil|biz|info|mobi|name|aero|jobs|museum"
+ "|travel|[a-z]{2}))(:[\\d]{1,5})?"
+ "(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?"
+ "((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?"
+ "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)"
+ "(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?"
+ "([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*"
+ "(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b");
Note the nested repetitions in the regular expression, such as (((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+
or ([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*
. A sufficiently complex payload can exploit this complexity to force the regex engine into catastrophic backtracking, taking exponential time to complete [1].
The pattern is used in the following way:
List<String> allowedProtocols = getAllowedProtocols();
for (String protocol : allowedProtocols) {
if (input.contains(protocol)) {
result.add(input);
}
}
if (result.isEmpty()) {
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
result.add(matcher.group());
}
}
This means that if the user-provided URL doesn’t contain any of the allowedProtocols
, the regular expression will be matched against it. Also, to reach extractUrls
from UtilHttp.canonicalizeParameterMap
, a parameter must look like an URL (or several) but it must not contain the string ://
at indexes 3 or 4 (so, for example, protocols http://
, ftp://
and https://
can’t be used):
public static Map<String, Object> canonicalizeParameterMap(Map<String, Object> paramMap) {
for (Map.Entry<String, Object> paramEntry : paramMap.entrySet()) {
if (paramEntry.getValue() instanceof String) {
String paramEntries = (String) paramEntry.getValue();
String[] stringValues = paramEntries.split(" ");
String params = "";
// Handles textareas, see OFBIZ-12249
if (stringValues.length > 0 && !paramEntry.getKey().equals("DUMMYPAGE")) {
for (String s : stringValues) {
// if the string contains only an URL beginning by http or ftp => no change to keep special chars
if (UtilValidate.isValidUrl(s) && (s.indexOf("://") == 4 || s.indexOf("://") == 3)) {
params = params + s + " ";
} else if (UtilValidate.isUrl(s) && !s.isEmpty()) {
// if the string contains not only an URL => concatenate possible canonicalized before and after, w/o changing the URL
String url = extractUrls(s).get(0); // There should be only 1 URL in a block, makes no sense else
So a parameter with the following form would reach extractUrls
:
parameter=somethingelse://www.a.org
The method canonicalizeParameterMap
is used to parse request parameters in several parts of the application. One of them is LoginWorker.extensionCheckLogin
, which is an event called to check whether a user is logged in. This means that the vulnerable regex in extractUrls
can be accessed by any unauthenticated user with a single HTTP request with a properly crafted parameter.
As an example, the following request would reproduce the denial of service due to exponential backtracking:
https://localhost:8443/partymgr/control/main?externalLoginKey=somethingelse://www.a.org/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!//!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/
Note that JDK 9 introduced important mitigations for this problem, so in order to reproduce the issue with the above example, Apache OFBiz must be run with JDK =< 8.
Impact
This issue may lead to a denial of service of the application server by resource consumption.
Resources
[1] https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
[2] https://github.com/google/re2j
CVE
- CVE-2022-29158
Credit
This issue was discovered and reported by the CodeQL team members @atorralba (Tony Torralba) and @joefarebrother (Joseph Farebrother).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2022-025
in any communication regarding this issue.