Remove experimental files

This commit is contained in:
Ed Minnix
2023-02-17 09:35:38 -05:00
committed by Tony Torralba
parent 3ff1a97e38
commit 6de946ef00
8 changed files with 0 additions and 315 deletions

View File

@@ -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);

View File

@@ -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>

View File

@@ -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"

View File

@@ -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
)
}
}

View File

@@ -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 |

View File

@@ -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;
}
}
}

View File

@@ -1 +0,0 @@
experimental/Security/CWE/CWE-321/HardcodedJwtKey.ql

View File

@@ -1 +0,0 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/auth0-jwt-2.3