Skip to content

Commit 6574f17

Browse files
Copilotowen-mc
andcommitted
Refactor regex-use sink kind to support polynomial ReDoS query
- Extended regexSinkKindInfo to handle plain "regex-use" sink kind - Plain "regex-use" defaults to non-full-string matching with string arg at index 0 - Updated comment in org.apache.commons.lang3.model.yml - Added test cases for RegExUtils methods in polynomial ReDoS test Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com>
1 parent de69d94 commit 6574f17

File tree

3 files changed

+38
-22
lines changed

3 files changed

+38
-22
lines changed

java/ql/lib/ext/org.apache.commons.lang3.model.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ extensions:
44
extensible: sinkModel
55
data:
66
- ["org.apache.commons.lang3", "SerializationUtils", False, "deserialize", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
7-
# Note these sinks do not use the sink kind `regex-use[0]` because the regex injection query needs to select them separately from
8-
# other `regex-use[0]` sinks in order to avoid FPs. As a result, these sinks are currently not used in the polynomial ReDoS query.
9-
# TODO: refactor the `regex-use%` sink kind so that the polynomial ReDoS query can also use these sinks.
7+
# Note these sinks use the sink kind `regex-use` (without brackets) because the regex injection query needs to select them
8+
# separately from other `regex-use[0]` sinks in order to avoid FPs. The polynomial ReDoS query handles the plain `regex-use`
9+
# sink kind by treating it as `regex-use[0]` (non-full-string matching with the string argument at index 0).
1010
- ["org.apache.commons.lang3", "RegExUtils", False, "removeAll", "(String,String)", "", "Argument[1]", "regex-use", "manual"]
1111
- ["org.apache.commons.lang3", "RegExUtils", False, "removeFirst", "(String,String)", "", "Argument[1]", "regex-use", "manual"]
1212
- ["org.apache.commons.lang3", "RegExUtils", False, "removePattern", "(String,String)", "", "Argument[1]", "regex-use", "manual"]

java/ql/lib/semmle/code/java/regex/RegexFlowConfigs.qll

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,32 @@ private class ExploitableStringLiteral extends StringLiteral {
2020
* `strArg` is the index of the argument to methods with this sink kind that
2121
* contain the string to be matched against, where -1 is the qualifier; or -2
2222
* if no such argument exists.
23-
*
24-
* Note that `regex-use` is deliberately not a possible value for `kind` here,
25-
* as it is used for regular expression injection sinks that need to be selected
26-
* separately from existing `regex-use[0]` sinks.
27-
* TODO: refactor the `regex-use%` sink kind so that the polynomial ReDoS query
28-
* can also use the `regex-use` sinks.
2923
*/
3024
private predicate regexSinkKindInfo(string kind, boolean full, int strArg) {
3125
sinkModel(_, _, _, _, _, _, _, kind, _, _) and
32-
exists(string fullStr, string strArgStr |
33-
(
34-
full = true and fullStr = "f"
35-
or
36-
full = false and fullStr = ""
37-
) and
38-
(
39-
strArgStr.toInt() = strArg
40-
or
41-
strArg = -2 and
42-
strArgStr = ""
26+
(
27+
exists(string fullStr, string strArgStr |
28+
(
29+
full = true and fullStr = "f"
30+
or
31+
full = false and fullStr = ""
32+
) and
33+
(
34+
strArgStr.toInt() = strArg
35+
or
36+
strArg = -2 and
37+
strArgStr = ""
38+
)
39+
|
40+
kind = "regex-use[" + fullStr + strArgStr + "]"
4341
)
44-
|
45-
kind = "regex-use[" + fullStr + strArgStr + "]"
42+
or
43+
// Plain `regex-use` sinks default to non-full-string matching with the string argument at index 0.
44+
// This is primarily used for methods like `RegExUtils.removeAll(text, regex)` where both the
45+
// pattern and the input are provided in the same call.
46+
kind = "regex-use" and
47+
full = false and
48+
strArg = 0
4649
)
4750
}
4851

java/ql/test/query-tests/security/CWE-730/PolyRedos/PolyRedosTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import java.util.function.Predicate;
33
import javax.servlet.http.HttpServletRequest;
44
import com.google.common.base.Splitter;
5+
import org.apache.commons.lang3.RegExUtils;
56

67
class PolyRedosTest {
78
void test(HttpServletRequest request) {
@@ -81,4 +82,16 @@ void test6(HttpServletRequest request) {
8182
p.matcher(request.getRequestURI()).matches();
8283
p.matcher(request.getCookies()[0].getName()).matches();
8384
}
85+
86+
void test7(HttpServletRequest request) {
87+
String tainted = request.getParameter("inp"); // $ Source
88+
String reg = "0\\.\\d+E?\\d+!";
89+
90+
RegExUtils.removeAll(tainted, reg); // $ Alert
91+
RegExUtils.removeFirst(tainted, reg); // $ Alert
92+
RegExUtils.removePattern(tainted, reg); // $ Alert
93+
RegExUtils.replaceAll(tainted, reg, "replacement"); // $ Alert
94+
RegExUtils.replaceFirst(tainted, reg, "replacement"); // $ Alert
95+
RegExUtils.replacePattern(tainted, reg, "replacement"); // $ Alert
96+
}
8497
}

0 commit comments

Comments
 (0)