Refactor to path query

This commit is contained in:
Tony Torralba
2021-08-04 13:05:18 +02:00
parent b586f3ec9c
commit 452fd9a8e3
3 changed files with 13 additions and 41 deletions

View File

@@ -1,8 +1,9 @@
/** /**
* @name Missing JWT signature check * @name Missing JWT signature check
* @description Failing to check the JWT signature may allow an attacker to forge their own tokens. * @description Failing to check the JWT signature may allow an attacker to forge their own tokens.
* @kind problem * @kind path-problem
* @problem.severity error * @problem.severity error
* @security-severity 7.8
* @precision high * @precision high
* @id java/missing-jwt-signature-check * @id java/missing-jwt-signature-check
* @tags security * @tags security
@@ -11,8 +12,9 @@
import java import java
import semmle.code.java.security.MissingJWTSignatureCheckQuery import semmle.code.java.security.MissingJWTSignatureCheckQuery
import DataFlow::PathGraph
from JwtParserWithInsecureParseSink sink, JwtParserWithSigningKeyExpr parserExpr from DataFlow::PathNode source, DataFlow::PathNode sink, MissingJwtSignatureCheckConf conf
where sink.asExpr() = parserExpr where conf.hasFlowPath(source, sink)
select sink.getParseMethodAccess(), "A signing key is set $@, but the signature is not verified.", select sink.getNode(), source, sink, "A signing key is set $@, but the signature is not verified.",
parserExpr.getSigningMethodAccess(), "here" source.getNode(), "here"

View File

@@ -5,43 +5,12 @@ import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.ExternalFlow import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.JWT import semmle.code.java.security.JWT
/**
* An expr that is a (sub-type of) `JwtParser` for which a signing key has been set.
*/
class JwtParserWithSigningKeyExpr extends Expr {
MethodAccess signingMa;
JwtParserWithSigningKeyExpr() { isSigningKeySetter(this, signingMa) }
/** Gets the method access that sets the signing key for this parser. */
MethodAccess getSigningMethodAccess() { result = signingMa }
}
/**
* Holds if `signingMa` directly or indirectly sets a signing key for `expr`, which is a `JwtParser`.
* The `setSigningKey` and `setSigningKeyResolver` methods set a signing key for a `JwtParser`.
*
* Directly means code like this (the signing key is set directly on a `JwtParser`):
* ```java
* Jwts.parser().setSigningKey(key).parse(token);
* ```
*
* Indirectly means code like this (the signing key is set on a `JwtParserBuilder` indirectly setting the key of `JwtParser` that is created by the call to `build`):
* ```java
* Jwts.parserBuilder().setSigningKey(key).build().parse(token);
* ```
*/
private predicate isSigningKeySetter(Expr expr, MethodAccess signingMa) {
any(SigningToInsecureMethodAccessDataFlow s)
.hasFlow(DataFlow::exprNode(signingMa), DataFlow::exprNode(expr))
}
/** /**
* Models flow from signing keys assignements to qualifiers of JWT insecure parsers. * Models flow from signing keys assignements to qualifiers of JWT insecure parsers.
* This is used to determine whether a `JwtParser` has a signing key set. * This is used to determine whether a `JwtParser` performing unsafe parsing has a signing key set.
*/ */
private class SigningToInsecureMethodAccessDataFlow extends DataFlow::Configuration { class MissingJwtSignatureCheckConf extends DataFlow::Configuration {
SigningToInsecureMethodAccessDataFlow() { this = "SigningToExprDataFlow" } MissingJwtSignatureCheckConf() { this = "SigningToExprDataFlow" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source) {
source instanceof JwtParserWithInsecureParseSource source instanceof JwtParserWithInsecureParseSource

View File

@@ -9,8 +9,9 @@ class HasMissingJwtSignatureCheckTest extends InlineExpectationsTest {
override predicate hasActualResult(Location location, string element, string tag, string value) { override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasMissingJwtSignatureCheck" and tag = "hasMissingJwtSignatureCheck" and
exists(JwtParserWithInsecureParseSink sink, JwtParserWithSigningKeyExpr parserExpr | exists(DataFlow::Node source, DataFlow::Node sink, MissingJwtSignatureCheckConf conf |
sink.asExpr() = parserExpr and conf.hasFlow(source, sink)
|
sink.getLocation() = location and sink.getLocation() = location and
element = sink.toString() and element = sink.toString() and
value = "" value = ""