mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
Merge pull request #20956 from owen-mc/java/improve-regex-sanitizer
Java: improve regex sanitizer for `java/ssrf`
This commit is contained in:
@@ -4,11 +4,46 @@ module;
|
||||
|
||||
import java
|
||||
|
||||
/** The class `java.util.regex.Matcher`. */
|
||||
class TypeRegexMatcher extends Class {
|
||||
TypeRegexMatcher() { this.hasQualifiedName("java.util.regex", "Matcher") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `matches` method of `java.util.regex.Matcher`.
|
||||
*/
|
||||
class MatcherMatchesMethod extends Method {
|
||||
MatcherMatchesMethod() {
|
||||
this.getDeclaringType() instanceof TypeRegexMatcher and
|
||||
this.hasName("matches")
|
||||
}
|
||||
}
|
||||
|
||||
/** The class `java.util.regex.Pattern`. */
|
||||
class TypeRegexPattern extends Class {
|
||||
TypeRegexPattern() { this.hasQualifiedName("java.util.regex", "Pattern") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `matches` method of `java.util.regex.Pattern`.
|
||||
*/
|
||||
class PatternMatchesMethod extends Method {
|
||||
PatternMatchesMethod() {
|
||||
this.getDeclaringType() instanceof TypeRegexPattern and
|
||||
this.hasName("matches")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `matcher` method of `java.util.regex.Pattern`.
|
||||
*/
|
||||
class PatternMatcherMethod extends Method {
|
||||
PatternMatcherMethod() {
|
||||
this.getDeclaringType() instanceof TypeRegexPattern and
|
||||
this.hasName("matcher")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `quote` method of the `java.util.regex.Pattern` class. */
|
||||
class PatternQuoteMethod extends Method {
|
||||
PatternQuoteMethod() {
|
||||
|
||||
@@ -166,22 +166,7 @@ private class HostComparisonSanitizer extends RequestForgerySanitizer {
|
||||
}
|
||||
|
||||
/**
|
||||
* A qualifier in a call to a `.matches()` method that is a sanitizer for URL redirects.
|
||||
*
|
||||
* Matches any method call where the method is named `matches`.
|
||||
* A comparison with a regular expression that is a sanitizer for URL redirects.
|
||||
*/
|
||||
private predicate isMatchesSanitizer(Guard guard, Expr e, boolean branch) {
|
||||
guard =
|
||||
any(MethodCall method |
|
||||
method.getMethod().getName() = "matches" and
|
||||
e = method.getQualifier() and
|
||||
branch = true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A qualifier in a call to `.matches()` that is a sanitizer for URL redirects.
|
||||
*/
|
||||
private class MatchesSanitizer extends RequestForgerySanitizer {
|
||||
MatchesSanitizer() { this = DataFlow::BarrierGuard<isMatchesSanitizer/3>::getABarrierNode() }
|
||||
}
|
||||
private class RegexpCheckRequestForgerySanitizer extends RequestForgerySanitizer instanceof RegexpCheckBarrier
|
||||
{ }
|
||||
|
||||
@@ -3,7 +3,9 @@ overlay[local?]
|
||||
module;
|
||||
|
||||
import java
|
||||
private import semmle.code.java.controlflow.Guards
|
||||
private import semmle.code.java.dataflow.DataFlow
|
||||
private import semmle.code.java.frameworks.Regex
|
||||
|
||||
/**
|
||||
* A node whose type is a simple type unlikely to carry taint, such as primitives and their boxed counterparts,
|
||||
@@ -29,3 +31,44 @@ class SimpleTypeSanitizer extends DataFlow::Node {
|
||||
this.getType() instanceof EnumType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `guard` holds with branch `branch` if `e` matches a regular expression.
|
||||
*
|
||||
* This is overapproximate: we do not attempt to reason about the correctness of the regexp.
|
||||
*
|
||||
* Use this if you want to define a derived `DataFlow::BarrierGuard` without
|
||||
* make the type recursive. Otherwise use `RegexpCheckBarrier`.
|
||||
*/
|
||||
predicate regexpMatchGuardChecks(Guard guard, Expr e, boolean branch) {
|
||||
exists(Method method, MethodCall mc |
|
||||
method = mc.getMethod() and
|
||||
guard = mc and
|
||||
branch = true
|
||||
|
|
||||
// `String.matches` and other `matches` methods.
|
||||
method.getName() = "matches" and
|
||||
e = mc.getQualifier()
|
||||
or
|
||||
method instanceof PatternMatchesMethod and
|
||||
e = mc.getArgument(1)
|
||||
or
|
||||
method instanceof MatcherMatchesMethod and
|
||||
exists(MethodCall matcherCall |
|
||||
matcherCall.getMethod() instanceof PatternMatcherMethod and
|
||||
e = matcherCall.getArgument(0) and
|
||||
DataFlow::localExprFlow(matcherCall, mc.getQualifier())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A check against a regular expression, considered as a barrier guard.
|
||||
*
|
||||
* This is overapproximate: we do not attempt to reason about the correctness of the regexp.
|
||||
*/
|
||||
class RegexpCheckBarrier extends DataFlow::Node {
|
||||
RegexpCheckBarrier() {
|
||||
this = DataFlow::BarrierGuard<regexpMatchGuardChecks/3>::getABarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user