Docs fixes

This commit is contained in:
Tony Torralba
2022-09-01 09:17:08 +02:00
parent 74cd532adc
commit 04c230b128
4 changed files with 36 additions and 34 deletions

View File

@@ -4,10 +4,10 @@
<qhelp> <qhelp>
<overview> <overview>
<p>By default, "dot" (<code>.</code>) in regular expressions matches all characters except newline characters <code>\n</code> and <p>By default, a "dot" (<code>.</code>) in a regular expression matches all characters except the new line characters <code>\n</code> and
<code>\r</code>. Regular expressions containing a dot can be bypassed with the characters \r(%0a) , \n(%0d) when the default regex <code>\r</code>. Regular expressions containing a dot can be bypassed with the characters <code>\r</code>(<code>%0a</code>) and
matching implementations of Java are used. When regular expressions serve to match protected resource patterns to grant access <code>\n</code>(<code>%0d</code>) when the default Java regular expression matching implementations are used. This becomes a security issue
to protected application resources, attackers can gain access to unauthorized paths.</p> if these regular expressions are used to decide whether to grant access to protected application resources.</p>
</overview> </overview>
<recommendation> <recommendation>
@@ -17,18 +17,15 @@ to address this vulnerability.</p>
</recommendation> </recommendation>
<example> <example>
<p>The following examples show the bad case and the good case respectively. The <code>bad</code> methods show a regex pattern allowing <p>The following snippets show a vulnerable example and a secure example respectively. The <code>bad</code> methods show a regex pattern allowing
bypass. In the <code>good</code> methods, it is shown how to solve this problem by either specifying the regex pattern correctly or 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
use the Java API that can detect new line characters. pattern correctly or using a Java API that properly matches new line characters.
</p> </p>
<sample src="DotRegex.java" /> <sample src="DotRegex.java" />
</example> </example>
<references> <references>
<li>Lay0us1:
<a href="https://github.com/Lay0us1/CVE-2022-32532">CVE 2022-22978: Authorization Bypass in RegexRequestMatcher</a>.
</li>
<li>Apache Shiro: <li>Apache Shiro:
<a href="https://github.com/apache/shiro/commit/6bcb92e06fa588b9c7790dd01bc02135d58d3f5b">Address the RegexRequestMatcher issue in 1.9.1</a>. <a href="https://github.com/apache/shiro/commit/6bcb92e06fa588b9c7790dd01bc02135d58d3f5b">Address the RegexRequestMatcher issue in 1.9.1</a>.
</li> </li>

View File

@@ -1,6 +1,6 @@
/** /**
* @name URL matched by permissive `.` in the regular expression * @name URL matched by permissive `.` in a regular expression
* @description URL validated with permissive `.` in regex are possibly vulnerable * @description URLs validated with a permissive `.` in regular expressions may be vulnerable
* to an authorization bypass. * to an authorization bypass.
* @kind path-problem * @kind path-problem
* @problem.severity warning * @problem.severity warning

View File

@@ -9,7 +9,7 @@ import semmle.code.java.security.UrlRedirect
import Regex import Regex
/** A string that ends with `.*` not prefixed with `\`. */ /** A string that ends with `.*` not prefixed with `\`. */
class PermissiveDotStr extends StringLiteral { private class PermissiveDotStr extends StringLiteral {
PermissiveDotStr() { PermissiveDotStr() {
exists(string s, int i | this.getValue() = s | exists(string s, int i | this.getValue() = s |
s.indexOf(".*") = i and s.indexOf(".*") = i and
@@ -19,7 +19,7 @@ class PermissiveDotStr extends StringLiteral {
} }
} }
/** Source model of remote flow source with servlets. */ /** Remote flow sources obtained from the URI of a serlvet request. */
private class GetServletUriSource extends SourceModelCsv { private class GetServletUriSource extends SourceModelCsv {
override predicate row(string row) { override predicate row(string row) {
row = row =
@@ -33,7 +33,7 @@ private class GetServletUriSource extends SourceModelCsv {
} }
} }
/** Sink of servlet dispatcher. */ /** The qualifier of a request dispatch method call. */
private class UrlDispatchSink extends UrlRedirectSink { private class UrlDispatchSink extends UrlRedirectSink {
UrlDispatchSink() { UrlDispatchSink() {
exists(MethodAccess ma | exists(MethodAccess ma |
@@ -51,7 +51,7 @@ private class ServletFilterMethod extends Method {
} }
} }
/** Sink of servlet filter. */ /** The qualifier of a servlet filter method call. */
private class UrlFilterSink extends UrlRedirectSink { private class UrlFilterSink extends UrlRedirectSink {
UrlFilterSink() { UrlFilterSink() {
exists(MethodAccess ma | exists(MethodAccess ma |
@@ -61,8 +61,8 @@ private class UrlFilterSink extends UrlRedirectSink {
} }
} }
/** A Spring framework annotation indicating remote uri user input. */ /** A Spring framework annotation indicating that a URI is user-provided. */
class SpringUriInputAnnotation extends Annotation { private class SpringUriInputAnnotation extends Annotation {
SpringUriInputAnnotation() { SpringUriInputAnnotation() {
this.getType() this.getType()
.hasQualifiedName("org.springframework.web.bind.annotation", .hasQualifiedName("org.springframework.web.bind.annotation",
@@ -70,7 +70,8 @@ class SpringUriInputAnnotation extends Annotation {
} }
} }
class SpringUriInputParameterSource extends DataFlow::Node { /** A user-provided URI parameter of a request mapping method. */
private class SpringUriInputParameterSource extends DataFlow::Node {
SpringUriInputParameterSource() { SpringUriInputParameterSource() {
this.asParameter() = this.asParameter() =
any(SpringRequestMappingParameter srmp | any(SpringRequestMappingParameter srmp |
@@ -82,7 +83,7 @@ class SpringUriInputParameterSource extends DataFlow::Node {
/** /**
* A data flow sink to construct regular expressions. * A data flow sink to construct regular expressions.
*/ */
class CompileRegexSink extends DataFlow::ExprNode { private class CompileRegexSink extends DataFlow::ExprNode {
CompileRegexSink() { CompileRegexSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() | exists(MethodAccess ma, Method m | m = ma.getMethod() |
( (
@@ -100,9 +101,9 @@ class CompileRegexSink extends DataFlow::ExprNode {
} }
/** /**
* A flow configuration for permissive dot regex. * A data flow configuration for regular expressions that include permissive dots.
*/ */
class PermissiveDotRegexConfig extends DataFlow2::Configuration { private class PermissiveDotRegexConfig extends DataFlow2::Configuration {
PermissiveDotRegexConfig() { this = "PermissiveDotRegex::PermissiveDotRegexConfig" } PermissiveDotRegexConfig() { this = "PermissiveDotRegex::PermissiveDotRegexConfig" }
override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof PermissiveDotStr } override predicate isSource(DataFlow2::Node src) { src.asExpr() instanceof PermissiveDotStr }
@@ -123,7 +124,8 @@ class PermissiveDotRegexConfig extends DataFlow2::Configuration {
} }
/** /**
* A taint-tracking configuration for untrusted user input used to match regular expressions. * A taint-tracking configuration for untrusted user input used to match regular expressions
* that include permissive dots.
*/ */
class MatchRegexConfiguration extends TaintTracking::Configuration { class MatchRegexConfiguration extends TaintTracking::Configuration {
MatchRegexConfiguration() { this = "PermissiveDotRegex::MatchRegexConfiguration" } MatchRegexConfiguration() { this = "PermissiveDotRegex::MatchRegexConfiguration" }
@@ -173,12 +175,15 @@ class MatchRegexConfiguration extends TaintTracking::Configuration {
} }
} }
/**
* A data flow sink representing a string being matched against a regular expression.
*/
abstract class MatchRegexSink extends DataFlow::ExprNode { } abstract class MatchRegexSink extends DataFlow::ExprNode { }
/** /**
* A data flow sink to string match regular expressions. * A string being matched against a regular expression.
*/ */
class StringMatchRegexSink extends MatchRegexSink { private class StringMatchRegexSink extends MatchRegexSink {
StringMatchRegexSink() { StringMatchRegexSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() | exists(MethodAccess ma, Method m | m = ma.getMethod() |
( (
@@ -190,9 +195,9 @@ class StringMatchRegexSink extends MatchRegexSink {
} }
/** /**
* A data flow sink to `pattern.matches` regular expressions. * A string being matched against a regular expression using a pattern.
*/ */
class PatternMatchRegexSink extends MatchRegexSink { private class PatternMatchRegexSink extends MatchRegexSink {
PatternMatchRegexSink() { PatternMatchRegexSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() | exists(MethodAccess ma, Method m | m = ma.getMethod() |
( (
@@ -204,9 +209,9 @@ class PatternMatchRegexSink extends MatchRegexSink {
} }
/** /**
* A data flow sink to `pattern.matcher` match regular expressions. * A string being used to create a pattern matcher.
*/ */
class PatternMatcherRegexSink extends MatchRegexSink { private class PatternMatcherRegexSink extends MatchRegexSink {
PatternMatcherRegexSink() { PatternMatcherRegexSink() {
exists(MethodAccess ma, Method m | m = ma.getMethod() | exists(MethodAccess ma, Method m | m = ma.getMethod() |
( (

View File

@@ -3,14 +3,14 @@
import java import java
/** /**
* The class `Pattern` for pattern match. * The class `java.util.regex.Pattern`.
*/ */
class Pattern extends RefType { class Pattern extends RefType {
Pattern() { this.hasQualifiedName("java.util.regex", "Pattern") } Pattern() { this.hasQualifiedName("java.util.regex", "Pattern") }
} }
/** /**
* The method `compile` for `Pattern`. * The method `compile` of `java.util.regex.Pattern`.
*/ */
class PatternCompileMethod extends Method { class PatternCompileMethod extends Method {
PatternCompileMethod() { PatternCompileMethod() {
@@ -20,7 +20,7 @@ class PatternCompileMethod extends Method {
} }
/** /**
* The method `matches` for `Pattern`. * The method `matches` of `java.util.regex.Pattern`.
*/ */
class PatternMatchMethod extends Method { class PatternMatchMethod extends Method {
PatternMatchMethod() { PatternMatchMethod() {
@@ -30,7 +30,7 @@ class PatternMatchMethod extends Method {
} }
/** /**
* The method `matcher` for `Pattern`. * The method `matcher` of `java.util.regex.Pattern`.
*/ */
class PatternMatcherMethod extends Method { class PatternMatcherMethod extends Method {
PatternMatcherMethod() { PatternMatcherMethod() {
@@ -40,7 +40,7 @@ class PatternMatcherMethod extends Method {
} }
/** /**
* The method `matches` for `String`. * The method `matches` of `java.lang.String`.
*/ */
class StringMatchMethod extends Method { class StringMatchMethod extends Method {
StringMatchMethod() { StringMatchMethod() {