Skip to content

Commit c0dd9dd

Browse files
authored
Merge pull request #10249 from atorralba/atorralba/regex-dot-bypass-docs
Java: Documentation fixes in the "Permissive dot regex" experimental query
2 parents b84dca9 + 6ffaa69 commit c0dd9dd

File tree

4 files changed

+36
-34
lines changed

4 files changed

+36
-34
lines changed

java/ql/src/experimental/Security/CWE/CWE-625/PermissiveDotRegex.qhelp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
<qhelp>
55

66
<overview>
7-
<p>By default, "dot" (<code>.</code>) in regular expressions matches all characters except newline characters <code>\n</code> and
8-
<code>\r</code>. Regular expressions containing a dot can be bypassed with the characters \r(%0a) , \n(%0d) when the default regex
9-
matching implementations of Java are used. When regular expressions serve to match protected resource patterns to grant access
10-
to protected application resources, attackers can gain access to unauthorized paths.</p>
7+
<p>By default, a "dot" (<code>.</code>) in a regular expression matches all characters except the newline characters <code>\n</code> and
8+
<code>\r</code>. Regular expressions containing a dot can be bypassed with the characters <code>\r</code>(<code>%0a</code>) and
9+
<code>\n</code>(<code>%0d</code>) when the default Java regular expression matching implementations are used. This becomes a security issue
10+
if these regular expressions are used to decide whether to grant access to protected application resources.</p>
1111
</overview>
1212

1313
<recommendation>
@@ -17,18 +17,15 @@ to address this vulnerability.</p>
1717
</recommendation>
1818

1919
<example>
20-
<p>The following examples show the bad case and the good case respectively. The <code>bad</code> methods show a regex pattern allowing
21-
bypass. In the <code>good</code> methods, it is shown how to solve this problem by either specifying the regex pattern correctly or
22-
use the Java API that can detect new line characters.
20+
<p>The following snippets show a vulnerable example and a secure example respectively. The <code>bad</code> methods show a regex pattern allowing
21+
a bypass by using line break characters. In the <code>good</code> methods, it is shown how to solve this problem by either specifying the regex
22+
pattern correctly or using a Java API that properly matches new line characters.
2323
</p>
2424

2525
<sample src="DotRegex.java" />
2626
</example>
2727

2828
<references>
29-
<li>Lay0us1:
30-
<a href="https://github.com/Lay0us1/CVE-2022-32532">CVE 2022-22978: Authorization Bypass in RegexRequestMatcher</a>.
31-
</li>
3229
<li>Apache Shiro:
3330
<a href="https://github.com/apache/shiro/commit/6bcb92e06fa588b9c7790dd01bc02135d58d3f5b">Address the RegexRequestMatcher issue in 1.9.1</a>.
3431
</li>

java/ql/src/experimental/Security/CWE/CWE-625/PermissiveDotRegex.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
2-
* @name URL matched by permissive `.` in the regular expression
3-
* @description URL validated with permissive `.` in regex are possibly vulnerable
2+
* @name URL matched by permissive `.` in a regular expression
3+
* @description URLs validated with a permissive `.` in regular expressions may be vulnerable
44
* to an authorization bypass.
55
* @kind path-problem
66
* @problem.severity warning

java/ql/src/experimental/Security/CWE/CWE-625/PermissiveDotRegexQuery.qll

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import semmle.code.java.security.UrlRedirect
99
import Regex
1010

1111
/** A string that ends with `.*` not prefixed with `\`. */
12-
class PermissiveDotStr extends StringLiteral {
12+
private class PermissiveDotStr extends StringLiteral {
1313
PermissiveDotStr() {
1414
exists(string s, int i | this.getValue() = s |
1515
s.indexOf(".*") = i and
@@ -19,7 +19,7 @@ class PermissiveDotStr extends StringLiteral {
1919
}
2020
}
2121

22-
/** Source model of remote flow source with servlets. */
22+
/** Remote flow sources obtained from the URI of a servlet request. */
2323
private class GetServletUriSource extends SourceModelCsv {
2424
override predicate row(string row) {
2525
row =
@@ -33,7 +33,7 @@ private class GetServletUriSource extends SourceModelCsv {
3333
}
3434
}
3535

36-
/** Sink of servlet dispatcher. */
36+
/** The qualifier of a request dispatch method call. */
3737
private class UrlDispatchSink extends UrlRedirectSink {
3838
UrlDispatchSink() {
3939
exists(MethodAccess ma |
@@ -51,7 +51,7 @@ private class ServletFilterMethod extends Method {
5151
}
5252
}
5353

54-
/** Sink of servlet filter. */
54+
/** The qualifier of a servlet filter method call. */
5555
private class UrlFilterSink extends UrlRedirectSink {
5656
UrlFilterSink() {
5757
exists(MethodAccess ma |
@@ -61,16 +61,17 @@ private class UrlFilterSink extends UrlRedirectSink {
6161
}
6262
}
6363

64-
/** A Spring framework annotation indicating remote uri user input. */
65-
class SpringUriInputAnnotation extends Annotation {
64+
/** A Spring framework annotation indicating that a URI is user-provided. */
65+
private class SpringUriInputAnnotation extends Annotation {
6666
SpringUriInputAnnotation() {
6767
this.getType()
6868
.hasQualifiedName("org.springframework.web.bind.annotation",
6969
["PathVariable", "RequestParam"])
7070
}
7171
}
7272

73-
class SpringUriInputParameterSource extends DataFlow::Node {
73+
/** A user-provided URI parameter of a request mapping method. */
74+
private class SpringUriInputParameterSource extends DataFlow::Node {
7475
SpringUriInputParameterSource() {
7576
this.asParameter() =
7677
any(SpringRequestMappingParameter srmp |
@@ -82,7 +83,7 @@ class SpringUriInputParameterSource extends DataFlow::Node {
8283
/**
8384
* A data flow sink to construct regular expressions.
8485
*/
85-
class CompileRegexSink extends DataFlow::ExprNode {
86+
private class CompileRegexSink extends DataFlow::ExprNode {
8687
CompileRegexSink() {
8788
exists(MethodAccess ma, Method m | m = ma.getMethod() |
8889
(
@@ -100,9 +101,9 @@ class CompileRegexSink extends DataFlow::ExprNode {
100101
}
101102

102103
/**
103-
* A flow configuration for permissive dot regex.
104+
* A data flow configuration for regular expressions that include permissive dots.
104105
*/
105-
class PermissiveDotRegexConfig extends DataFlow2::Configuration {
106+
private class PermissiveDotRegexConfig extends DataFlow2::Configuration {
106107
PermissiveDotRegexConfig() { this = "PermissiveDotRegex::PermissiveDotRegexConfig" }
107108

108109
override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof PermissiveDotStr }
@@ -123,7 +124,8 @@ class PermissiveDotRegexConfig extends DataFlow2::Configuration {
123124
}
124125

125126
/**
126-
* A taint-tracking configuration for untrusted user input used to match regular expressions.
127+
* A taint-tracking configuration for untrusted user input used to match regular expressions
128+
* that include permissive dots.
127129
*/
128130
class MatchRegexConfiguration extends TaintTracking::Configuration {
129131
MatchRegexConfiguration() { this = "PermissiveDotRegex::MatchRegexConfiguration" }
@@ -173,12 +175,15 @@ class MatchRegexConfiguration extends TaintTracking::Configuration {
173175
}
174176
}
175177

178+
/**
179+
* A data flow sink representing a string being matched against a regular expression.
180+
*/
176181
abstract class MatchRegexSink extends DataFlow::ExprNode { }
177182

178183
/**
179-
* A data flow sink to string match regular expressions.
184+
* A string being matched against a regular expression.
180185
*/
181-
class StringMatchRegexSink extends MatchRegexSink {
186+
private class StringMatchRegexSink extends MatchRegexSink {
182187
StringMatchRegexSink() {
183188
exists(MethodAccess ma, Method m | m = ma.getMethod() |
184189
(
@@ -190,9 +195,9 @@ class StringMatchRegexSink extends MatchRegexSink {
190195
}
191196

192197
/**
193-
* A data flow sink to `pattern.matches` regular expressions.
198+
* A string being matched against a regular expression using a pattern.
194199
*/
195-
class PatternMatchRegexSink extends MatchRegexSink {
200+
private class PatternMatchRegexSink extends MatchRegexSink {
196201
PatternMatchRegexSink() {
197202
exists(MethodAccess ma, Method m | m = ma.getMethod() |
198203
(
@@ -204,9 +209,9 @@ class PatternMatchRegexSink extends MatchRegexSink {
204209
}
205210

206211
/**
207-
* A data flow sink to `pattern.matcher` match regular expressions.
212+
* A string being used to create a pattern matcher.
208213
*/
209-
class PatternMatcherRegexSink extends MatchRegexSink {
214+
private class PatternMatcherRegexSink extends MatchRegexSink {
210215
PatternMatcherRegexSink() {
211216
exists(MethodAccess ma, Method m | m = ma.getMethod() |
212217
(

java/ql/src/experimental/Security/CWE/CWE-625/Regex.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import java
44

55
/**
6-
* The class `Pattern` for pattern match.
6+
* The class `java.util.regex.Pattern`.
77
*/
88
class Pattern extends RefType {
99
Pattern() { this.hasQualifiedName("java.util.regex", "Pattern") }
1010
}
1111

1212
/**
13-
* The method `compile` for `Pattern`.
13+
* The method `compile` of `java.util.regex.Pattern`.
1414
*/
1515
class PatternCompileMethod extends Method {
1616
PatternCompileMethod() {
@@ -20,7 +20,7 @@ class PatternCompileMethod extends Method {
2020
}
2121

2222
/**
23-
* The method `matches` for `Pattern`.
23+
* The method `matches` of `java.util.regex.Pattern`.
2424
*/
2525
class PatternMatchMethod extends Method {
2626
PatternMatchMethod() {
@@ -30,7 +30,7 @@ class PatternMatchMethod extends Method {
3030
}
3131

3232
/**
33-
* The method `matcher` for `Pattern`.
33+
* The method `matcher` of `java.util.regex.Pattern`.
3434
*/
3535
class PatternMatcherMethod extends Method {
3636
PatternMatcherMethod() {
@@ -40,7 +40,7 @@ class PatternMatcherMethod extends Method {
4040
}
4141

4242
/**
43-
* The method `matches` for `String`.
43+
* The method `matches` of `java.lang.String`.
4444
*/
4545
class StringMatchMethod extends Method {
4646
StringMatchMethod() {

0 commit comments

Comments
 (0)