Reducing ReDoS attacks in our Software
In May, 2024, IriusRisk signed the CISA Secure by Design Pledge, which has over 200 signatures and commitments. As a company, we are an enterprise software manufacturer and provide software products to customers within the United States - and other regions around the world. As a part of this pledge, and for our own ongoing improvements, we have successfully avoided a specific vulnerability in our application, through our design and implementation processes. This write up aims to share how we avoided his vulnerability.
We needed to ensure global protection against ReDoS attacks, regardless of the number of patterns present in our software or attack surfaces involving user input regular expressions.
To mitigate ReDoS risks, we avoid the use of Java's Pattern and Matcher classes, which use a vulnerable backtracking algorithm, susceptible to such attacks.
We made use of the google-re2 java library, instead, because it uses a linear-time algorithm based on finite automata, which ensures that the time complexity of matching is always linear with respect to the length of the input string.
This means that even for an evil regex and a large input string, the matching process won’t exhibit exponential time behavior, which is the primary cause of ReDoS vulnerabilities.
So we wrapped all our regular expressions operations in a single class in order to have control about how and where we are using them. This class exposes all the methods needed for regular expressions using the google-re2 library.
Next, we enforced the use of this wrapper by prohibiting the use of Java's Pattern and Matcher classes.
We also ensured that our Groovy code didn't utilize operators like ~, =~, and ==~, which rely on Java's Pattern and Matcher classes.
So we created an architectural test that checks:
- Any of our Java classes import any class from the javax.utils.regex package
- Any of our Groovy classes uses the groovy regex operators
- Only the wrapper class can import the google-re2 library
Moreover, we tested the wrapper class to ensure it could handle malicious regular expressions and large input strings (thousands of characters) within a one-second timeframe.
In conclusion, we have effectively mitigated the risk of ReDoS attacks across our software. Malicious users attempting to exploit vulnerabilities through malicious regular expressions will encounter linear processing times, preventing resource abuse and potential denial-of-service attacks.
Additionally, by centralizing regular expression operations in a wrapper class, we have minimized the risk of performance degradation due to poorly constructed regular expressions.