mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Remove experimental files
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
// BAD: Get secret from hardcoded string then sign a JWT token
|
||||
Algorithm algorithm = Algorithm.HMAC256("hardcoded_secret");
|
||||
JWT.create()
|
||||
.withClaim("username", username)
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
// BAD: Get secret from hardcoded string then verify a JWT token
|
||||
JWTVerifier verifier = JWT.require(Algorithm.HMAC256("hardcoded_secret"))
|
||||
.withIssuer(ISSUER)
|
||||
.build();
|
||||
verifier.verify(token);
|
||||
|
||||
// GOOD: Get secret from system configuration then sign a token
|
||||
String tokenSecret = System.getenv("SECRET_KEY");
|
||||
Algorithm algorithm = Algorithm.HMAC256(tokenSecret);
|
||||
JWT.create()
|
||||
.withClaim("username", username)
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
// GOOD: Get secret from environment variable then verify a JWT token
|
||||
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(System.getenv("SECRET_KEY")))
|
||||
.withIssuer(ISSUER)
|
||||
.build();
|
||||
verifier.verify(token);
|
||||
@@ -1,46 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
JWT (JSON Web Token) is an open standard (RFC 7519) that defines a way to provide information
|
||||
within a JSON object between two parties. JWT is widely used for sharing security information
|
||||
between two parties in web applications. Each JWT contains encoded JSON objects, including a
|
||||
set of claims. JWTs are signed using a cryptographic algorithm to ensure that the claims cannot
|
||||
be altered after the token is issued.
|
||||
</p>
|
||||
<p>
|
||||
The most basic mistake is using hardcoded secrets for JWT generation/verification. This allows
|
||||
an attacker to forge the token if the source code (and JWT secret in it) is publicly exposed or
|
||||
leaked, which leads to authentication bypass or privilege escalation.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Generating a cryptographically secure secret key during application initialization and using this
|
||||
generated key for JWT signing/verification requests can prevent this vulnerability. Or safely store
|
||||
the secret key in a key vault that cannot be leaked in source code.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following examples show the bad case and the good case respectively. The <code>bad</code>
|
||||
methods show a hardcoded secret key is used to sign and verify JWT tokens. In the <code>good</code>
|
||||
method, the secret key is loaded from a system environment during application initialization.
|
||||
</p>
|
||||
<sample src="HardcodedJwtKey.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Semgrep Blog:
|
||||
<a href="https://r2c.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/">Hardcoded secrets, unverified tokens, and other common JWT mistakes</a>
|
||||
</li>
|
||||
<li>
|
||||
CVE-2022-24860:
|
||||
<a href="https://nvd.nist.gov/vuln/detail/CVE-2022-24860">Databasir 1.01 has Use of Hard-coded Cryptographic Key vulnerability.</a>
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @name Use of a hardcoded key for signing JWT
|
||||
* @description Using a hardcoded key for signing JWT can allow an attacker to compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id java/hardcoded-jwt-key
|
||||
* @tags security
|
||||
* experimental
|
||||
* external/cwe/cwe-321
|
||||
*/
|
||||
|
||||
import java
|
||||
import HardcodedJwtKey
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedJwtKeyConfiguration cfg
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "$@ is used to sign a JWT token.", source.getNode(),
|
||||
"Hardcoded String"
|
||||
@@ -1,131 +0,0 @@
|
||||
/**
|
||||
* Provides sources and sinks for detecting JWT token signing vulnerabilities.
|
||||
*/
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
private class ActivateModels extends ActiveExperimentalModels {
|
||||
ActivateModels() { this = "hardcoded-jwt-key" }
|
||||
}
|
||||
|
||||
/** The class `com.auth0.jwt.JWT`. */
|
||||
class Jwt extends RefType {
|
||||
Jwt() { this.hasQualifiedName("com.auth0.jwt", "JWT") }
|
||||
}
|
||||
|
||||
/** The class `com.auth0.jwt.JWTCreator.Builder`. */
|
||||
class JwtBuilder extends RefType {
|
||||
JwtBuilder() { this.hasQualifiedName("com.auth0.jwt", "JWTCreator$Builder") }
|
||||
}
|
||||
|
||||
/** The class `com.auth0.jwt.algorithms.Algorithm`. */
|
||||
class JwtAlgorithm extends RefType {
|
||||
JwtAlgorithm() { this.hasQualifiedName("com.auth0.jwt.algorithms", "Algorithm") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface `com.auth0.jwt.interfaces.JWTVerifier` or its implementation
|
||||
* `com.auth0.jwt.JWTVerifier`.
|
||||
*/
|
||||
class JwtVerifier extends RefType {
|
||||
JwtVerifier() {
|
||||
this.hasQualifiedName(["com.auth0.jwt", "com.auth0.jwt.interfaces"], "JWTVerifier")
|
||||
}
|
||||
}
|
||||
|
||||
/** A method that creates an instance of `com.auth0.jwt.algorithms.Algorithm`. */
|
||||
class GetAlgorithmMethod extends Method {
|
||||
GetAlgorithmMethod() {
|
||||
this.getDeclaringType() instanceof JwtAlgorithm and
|
||||
this.getName().matches(["HMAC%", "ECDSA%", "RSA%"])
|
||||
}
|
||||
}
|
||||
|
||||
/** The `require` method of `com.auth0.jwt.JWT`. */
|
||||
class RequireMethod extends Method {
|
||||
RequireMethod() {
|
||||
this.getDeclaringType() instanceof Jwt and
|
||||
this.hasName("require")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `sign` method of `com.auth0.jwt.JWTCreator.Builder`. */
|
||||
class SignTokenMethod extends Method {
|
||||
SignTokenMethod() {
|
||||
this.getDeclaringType() instanceof JwtBuilder and
|
||||
this.hasName("sign")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `verify` method of `com.auth0.jwt.interfaces.JWTVerifier`. */
|
||||
class VerifyTokenMethod extends Method {
|
||||
VerifyTokenMethod() {
|
||||
this.getDeclaringType() instanceof JwtVerifier and
|
||||
this.hasName("verify")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow source for JWT token signing vulnerabilities.
|
||||
*/
|
||||
abstract class JwtKeySource extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for JWT token signing vulnerabilities.
|
||||
*/
|
||||
abstract class JwtTokenSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A hardcoded string literal as a source for JWT token signing vulnerabilities.
|
||||
*/
|
||||
class HardcodedKeyStringSource extends JwtKeySource {
|
||||
HardcodedKeyStringSource() { exists(this.asExpr().(CompileTimeConstantExpr).getStringValue()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression used to sign JWT tokens as a sink of JWT token signing vulnerabilities.
|
||||
*/
|
||||
private class SignTokenSink extends JwtTokenSink {
|
||||
SignTokenSink() {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof SignTokenMethod and
|
||||
this.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression used to verify JWT tokens as a sink of JWT token signing vulnerabilities.
|
||||
*/
|
||||
private class VerifyTokenSink extends JwtTokenSink {
|
||||
VerifyTokenSink() {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof VerifyTokenMethod and
|
||||
this.asExpr() = ma.getQualifier()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration depicting taint flow for checking JWT token signing vulnerabilities.
|
||||
*/
|
||||
class HardcodedJwtKeyConfiguration extends TaintTracking::Configuration {
|
||||
HardcodedJwtKeyConfiguration() { this = "Hard-coded JWT Signing Key" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof JwtKeySource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof JwtTokenSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node prev, DataFlow::Node succ) {
|
||||
exists(MethodAccess ma |
|
||||
(
|
||||
ma.getMethod() instanceof GetAlgorithmMethod or
|
||||
ma.getMethod() instanceof RequireMethod
|
||||
) and
|
||||
prev.asExpr() = ma.getArgument(0) and
|
||||
succ.asExpr() = ma
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
edges
|
||||
| HardcodedJwtKey.java:15:33:15:38 | SECRET : String | HardcodedJwtKey.java:19:49:19:54 | SECRET : String |
|
||||
| HardcodedJwtKey.java:15:33:15:38 | SECRET : String | HardcodedJwtKey.java:42:62:42:67 | SECRET : String |
|
||||
| HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" : String | HardcodedJwtKey.java:15:33:15:38 | SECRET : String |
|
||||
| HardcodedJwtKey.java:19:49:19:54 | SECRET : String | HardcodedJwtKey.java:25:23:25:31 | algorithm |
|
||||
| HardcodedJwtKey.java:42:32:42:69 | require(...) : Verification | HardcodedJwtKey.java:42:32:43:35 | withIssuer(...) : Verification |
|
||||
| HardcodedJwtKey.java:42:32:43:35 | withIssuer(...) : Verification | HardcodedJwtKey.java:42:32:44:24 | build(...) : JWTVerifier |
|
||||
| HardcodedJwtKey.java:42:32:44:24 | build(...) : JWTVerifier | HardcodedJwtKey.java:46:13:46:20 | verifier |
|
||||
| HardcodedJwtKey.java:42:62:42:67 | SECRET : String | HardcodedJwtKey.java:42:32:42:69 | require(...) : Verification |
|
||||
nodes
|
||||
| HardcodedJwtKey.java:15:33:15:38 | SECRET : String | semmle.label | SECRET : String |
|
||||
| HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" : String | semmle.label | "hardcoded_secret" : String |
|
||||
| HardcodedJwtKey.java:19:49:19:54 | SECRET : String | semmle.label | SECRET : String |
|
||||
| HardcodedJwtKey.java:25:23:25:31 | algorithm | semmle.label | algorithm |
|
||||
| HardcodedJwtKey.java:42:32:42:69 | require(...) : Verification | semmle.label | require(...) : Verification |
|
||||
| HardcodedJwtKey.java:42:32:43:35 | withIssuer(...) : Verification | semmle.label | withIssuer(...) : Verification |
|
||||
| HardcodedJwtKey.java:42:32:44:24 | build(...) : JWTVerifier | semmle.label | build(...) : JWTVerifier |
|
||||
| HardcodedJwtKey.java:42:62:42:67 | SECRET : String | semmle.label | SECRET : String |
|
||||
| HardcodedJwtKey.java:46:13:46:20 | verifier | semmle.label | verifier |
|
||||
subpaths
|
||||
#select
|
||||
| HardcodedJwtKey.java:25:23:25:31 | algorithm | HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" : String | HardcodedJwtKey.java:25:23:25:31 | algorithm | $@ is used to sign a JWT token. | HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" | Hardcoded String |
|
||||
| HardcodedJwtKey.java:25:23:25:31 | algorithm | HardcodedJwtKey.java:19:49:19:54 | SECRET : String | HardcodedJwtKey.java:25:23:25:31 | algorithm | $@ is used to sign a JWT token. | HardcodedJwtKey.java:19:49:19:54 | SECRET | Hardcoded String |
|
||||
| HardcodedJwtKey.java:46:13:46:20 | verifier | HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" : String | HardcodedJwtKey.java:46:13:46:20 | verifier | $@ is used to sign a JWT token. | HardcodedJwtKey.java:15:42:15:59 | "hardcoded_secret" | Hardcoded String |
|
||||
| HardcodedJwtKey.java:46:13:46:20 | verifier | HardcodedJwtKey.java:42:62:42:67 | SECRET : String | HardcodedJwtKey.java:46:13:46:20 | verifier | $@ is used to sign a JWT token. | HardcodedJwtKey.java:42:62:42:67 | SECRET | Hardcoded String |
|
||||
@@ -1,65 +0,0 @@
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
|
||||
public class HardcodedJwtKey {
|
||||
// 15 minutes
|
||||
private static final long ACCESS_EXPIRE_TIME = 1000 * 60 * 15;
|
||||
|
||||
private static final String ISSUER = "example_com";
|
||||
|
||||
private static final String SECRET = "hardcoded_secret";
|
||||
|
||||
// BAD: Get secret from hardcoded string then sign a JWT token
|
||||
public String accessTokenBad(String username) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(SECRET);
|
||||
|
||||
return JWT.create()
|
||||
.withExpiresAt(new Date(new Date().getTime() + ACCESS_EXPIRE_TIME))
|
||||
.withIssuer(ISSUER)
|
||||
.withClaim("username", username)
|
||||
.sign(algorithm); // $ HardcodedCredentialsApiCall
|
||||
}
|
||||
|
||||
// GOOD: Get secret from system configuration then sign a token
|
||||
public String accessTokenGood(String username) {
|
||||
String tokenSecret = System.getenv("SECRET_KEY");
|
||||
Algorithm algorithm = Algorithm.HMAC256(tokenSecret);
|
||||
|
||||
return JWT.create()
|
||||
.withExpiresAt(new Date(new Date().getTime() + ACCESS_EXPIRE_TIME))
|
||||
.withIssuer(ISSUER)
|
||||
.withClaim("username", username)
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
// BAD: Get secret from hardcoded string then verify a JWT token
|
||||
public boolean verifyTokenBad(String token) {
|
||||
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET))
|
||||
.withIssuer(ISSUER)
|
||||
.build();
|
||||
try {
|
||||
verifier.verify(token); // $ HardcodedCredentialsApiCall
|
||||
return true;
|
||||
} catch (JWTVerificationException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// GOOD: Get secret from environment variable then verify a JWT token
|
||||
public boolean verifyTokenGood(String token) {
|
||||
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(System.getenv("SECRET_KEY")))
|
||||
.withIssuer(ISSUER)
|
||||
.build();
|
||||
try {
|
||||
verifier.verify(token);
|
||||
return true;
|
||||
} catch (JWTVerificationException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
experimental/Security/CWE/CWE-321/HardcodedJwtKey.ql
|
||||
@@ -1 +0,0 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/auth0-jwt-2.3
|
||||
Reference in New Issue
Block a user