Go: Promote go/hardcoded-key from experimental

This commit is contained in:
Tony Torralba
2024-02-06 15:58:23 +01:00
parent 337db6b29b
commit ba1faea630
43 changed files with 354 additions and 659 deletions

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/cristalhq/jwt/$ANYVERSION", "", True, "NewSignerHS", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/dgrijalva/jwt-go", "Token", True, "SignedString", "", "", "Argument[0]", "credentials-key", "manual"]
- ["github.com/dgrijalva/jwt-go", "SigningMethod", True, "Sign", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/form3tech-oss/jwt-go", "Token", True, "SignedString", "", "", "Argument[0]", "credentials-key", "manual"]
- ["github.com/form3tech-oss/jwt-go", "SigningMethod", True, "Sign", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/go-chi/jwtauth/$ANYVERSION", "", True, "New", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/go-kit/kit/auth/jwt", "", True, "NewSigner", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/golang-jwt/jwt/$ANYVERSION", "Token", True, "SignedString", "", "", "Argument[0]", "credentials-key", "manual"]
- ["github.com/golang-jwt/jwt/$ANYVERSION", "SigningMethod", True, "Sign", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/kataras/iris/$ANYVERSION/middleware/jwt", "", True, "NewSigner", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,10 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/kataras/jwt", "Keys", True, "Register", "", "", "Argument[3]", "credentials-key", "manual"]
- ["github.com/kataras/jwt", "", True, "Sign", "", "", "Argument[1]", "credentials-key", "manual"]
- ["github.com/kataras/jwt", "", True, "SignEncrypted", "", "", "Argument[1]", "credentials-key", "manual"]
- ["github.com/kataras/jwt", "", True, "SignEncryptedWithHeader", "", "", "Argument[1]", "credentials-key", "manual"]
- ["github.com/kataras/jwt", "", True, "SignWithHeader", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/lestrrat-go/jwx/$ANYVERSION/jwk", "", True, "New", "", "", "Argument[0]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/lestrrat-go/jwx", "", True, "New", "", "", "Argument[0]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/lestrrat/go-jwx/jwk", "", True, "New", "", "", "Argument[0]", "credentials-key", "manual"]

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/ory/fosite/token/jwt", "Token", True, "SignedString", "", "", "Argument[0]", "credentials-key", "manual"]
- ["github.com/ory/fosite/token/jwt", "SigningMethod", True, "Sign", "", "", "Argument[1]", "credentials-key", "manual"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: summaryModel
data:
- ["math/big", "Int", False, "Int64", "", "", "Argument[-1]", "ReturnValue[0]", "taint", "manual"]

View File

@@ -0,0 +1,158 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* hardcoded credentials, as well as extension points
* for adding your own.
*/
import go
private import semmle.go.StringOps
private import semmle.go.dataflow.ExternalFlow
private import semmle.go.security.Jwt
/**
* Provides default sources, sinks and sanitizers for reasoning about
* hardcoded credentials, as well as extension points
* for adding your own.
*/
module HardcodedCredentials {
/** A data flow source for hardcoded credentials. */
abstract class Source extends DataFlow::Node { }
/** A data flow sink for hardcoded credentials. */
abstract class Sink extends DataFlow::Node { }
/** A sanitizer for hardcoded credentials. */
abstract class Sanitizer extends DataFlow::Node { }
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/** Tracks taint flow for reasoning about hardcoded credentials. */
module Flow = TaintTracking::Global<Config>;
/** A hardcoded string literal as a source for hardcoded credentials. */
private class HardcodedStringSource extends Source {
HardcodedStringSource() { this.asExpr() instanceof StringLit }
}
/** A use of a credential. */
private class CredentialsSink extends Sink {
CredentialsSink() { exists(string s | s.matches("credentials-%") | sinkNode(this, s)) }
}
/**
* Holds if the guard `g` in its branch `branch` validates the expression `e`
* by comparing it to a disallowed literal.
*/
private predicate constantValueCheck(DataFlow::Node g, Expr e, boolean branch) {
exists(Literal lit, DataFlow::EqualityTestNode eq | eq = g |
eq.getAnOperand().asExpr() = e and
eq.getAnOperand().asExpr() = lit and
e != lit and
branch = eq.getPolarity().booleanNot()
)
}
/**
* A value validated by comparing it to a disallowed constant value.
* For example, in the context `if key != "invalid_key" { ... }`,
* if `"invalid_key"` is indeed the only dangerous key then guarded uses of `key` are likely
* to be safe.
*/
private class CompareExprSanitizer extends Sanitizer {
CompareExprSanitizer() {
this = DataFlow::BarrierGuard<constantValueCheck/3>::getABarrierNode()
}
}
/**
* A value returned with an error.
*
* Typically this means contexts like `return "", errors.New("Oh no")`,
* where we can be reasonably confident downstream users will not mistake
* that empty string for a usable key.
*/
private class ReturnedAlongsideErrorSanitizer extends Sanitizer {
ReturnedAlongsideErrorSanitizer() {
exists(ReturnStmt r, DataFlow::CallNode c |
c.getTarget().hasQualifiedName("errors", "New") and
r.getNumChild() > 1 and
r.getAChild() = c.getAResult().getASuccessor*().asExpr() and
r.getAChild() = this.asExpr()
)
}
}
/**
* A value returned alongside an error-value that is known
* to be non-nil by virtue of a guarding check.
*
* For example, `if err != nil { return "", err }` is unlikely to be
* contributing a dangerous hardcoded key.
*/
private class ReturnedAlongsideErrorSanitizerGuard extends Sanitizer {
ReturnedAlongsideErrorSanitizerGuard() {
exists(ControlFlow::ConditionGuardNode guard, SsaWithFields errorVar, ReturnStmt r |
guard.ensuresNeq(errorVar.getAUse(), Builtin::nil().getARead()) and
guard.dominates(this.getBasicBlock()) and
r.getExpr(1) = errorVar.getAUse().asExpr() and
this.asExpr() = r.getExpr(0)
)
}
}
/** The result of a formatting string call. */
private class FormattingSanitizer extends Sanitizer {
FormattingSanitizer() { any(StringOps::Formatting::StringFormatCall s).getAResult() = this }
}
private string getRandIntFunctionName() {
result =
[
"ExpFloat64", "Float32", "Float64", "Int", "Int31", "Int31n", "Int63", "Int63n", "Intn",
"NormFloat64", "Uint32", "Uint64"
]
}
private DataFlow::CallNode getARandIntCall() {
exists(Function f | f = result.getTarget() |
f.hasQualifiedName("math/rand", getRandIntFunctionName()) or
f.(Method).hasQualifiedName("math/rand", "Rand", getRandIntFunctionName()) or
f.hasQualifiedName("crypto/rand", "Int")
)
}
private DataFlow::CallNode getARandReadCall() {
result.getTarget().hasQualifiedName("crypto/rand", "Read")
}
/**
* Holds if taint flows in one local step from `prev` to `succ`, or
* through a binary operation such as a modulo `%` operation or an addition `+` operation.
*/
private predicate localTaintStepIncludingBinaryExpr(DataFlow::Node prev, DataFlow::Node succ) {
TaintTracking::localTaintStep(prev, succ)
or
exists(BinaryExpr b | b.getAnOperand() = prev.asExpr() | succ.asExpr() = b)
}
/** A read from a slice with a random index. */
private class RandSliceSanitizer extends Sanitizer, DataFlow::ElementReadNode {
RandSliceSanitizer() {
exists(DataFlow::Node randomValue, DataFlow::Node index |
randomValue = getARandIntCall().getAResult()
or
randomValue.(DataFlow::PostUpdateNode).getPreUpdateNode() =
getARandReadCall().getArgument(0)
|
localTaintStepIncludingBinaryExpr*(randomValue, index) and
this.reads(_, index)
)
}
}
}

View File

@@ -0,0 +1,44 @@
/**
* Provides classes and predicates for reasoning about JSON Web Tokens (JWT).
*/
import go
private import semmle.go.security.HardcodedCredentials
private class IrisJwt extends HardcodedCredentials::Sink {
IrisJwt() {
exists(Field f |
f.hasQualifiedName(package("github.com/kataras/iris", "middleware/jwt"), "Signer", "Key") and
f.getAWrite().getRhs() = this
)
}
}
private class GogfJwtSign extends HardcodedCredentials::Sink {
GogfJwtSign() {
exists(Field f |
f.hasQualifiedName(package("github.com/gogf/gf-jwt", ""), "GfJWTMiddleware", "Key") and
f.getAWrite().getRhs() = this
)
}
}
private class GinJwtSign extends HardcodedCredentials::Sink {
GinJwtSign() {
exists(Field f |
f.hasQualifiedName(package("github.com/appleboy/gin-jwt", ""), "GinJWTMiddleware", "Key") and
f.getAWrite().getRhs() = this
)
}
}
private class SquareJoseKey extends HardcodedCredentials::Sink {
SquareJoseKey() {
exists(Field f, string pkg |
pkg = ["github.com/square/go-jose/v3", "gopkg.in/square/go-jose.v2"]
|
f.hasQualifiedName(pkg, ["Recipient", "SigningKey"], "Key") and
f.getAWrite().getRhs() = this
)
}
}

View File

@@ -14,6 +14,7 @@
*/
import go
import semmle.go.security.HardcodedCredentials
import semmle.go.security.SensitiveActions
/**
@@ -31,22 +32,35 @@ predicate isSensitive(DataFlow::Node sink, SensitiveExpr::Classification type) {
)
}
from DataFlow::Node source, string message, DataFlow::Node sink, SensitiveExpr::Classification type
where
predicate sensitiveAssignment(
DataFlow::Node source, DataFlow::Node sink, SensitiveExpr::Classification type
) {
exists(string val | val = source.getStringValue() and val != "" |
isSensitive(sink, type) and
DataFlow::localFlow(source, sink) and
isSensitive(sink, type) and
// allow obvious dummy/test values
not PasswordHeuristics::isDummyPassword(val) and
not sink.asExpr().(Ident).getName().regexpMatch(HeuristicNames::notSensitive())
) and
)
}
predicate hardcodedPrivateKey(DataFlow::Node node, SensitiveExpr::Classification type) {
node.getStringValue()
.regexpMatch("(?s)-+BEGIN\\b.*\\bPRIVATE KEY-+.+-+END\\b.*\\bPRIVATE KEY-+\n?") and
(node.asExpr() instanceof StringLit or node.asExpr() instanceof AddExpr) and
type = SensitiveExpr::certificate()
}
from DataFlow::Node source, string message, DataFlow::Node sink, SensitiveExpr::Classification type
where
sensitiveAssignment(source, sink, type) and
message = "Hard-coded $@."
or
source
.getStringValue()
.regexpMatch("(?s)-+BEGIN\\b.*\\bPRIVATE KEY-+.+-+END\\b.*\\bPRIVATE KEY-+\n?") and
(source.asExpr() instanceof StringLit or source.asExpr() instanceof AddExpr) and
sink = source and
type = SensitiveExpr::certificate() and
hardcodedPrivateKey(source, type) and
source = sink and
message = "Hard-coded private key."
or
HardcodedCredentials::Flow::flow(source, sink) and
type = SensitiveExpr::password() and
message = "Hard-coded credential."
select sink, message, source, type.toString()

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* The query "Use of a hardcoded key for signing JWT" (`go/hardcoded-key`) has been promoted from experimental to the main query pack. Its results will now appear by default as part of `go/hardcoded-credentials`. This query was originally [submitted as an experimental query by @porcupineyhairs](https://github.com/github/codeql/pull/9378).

View File

@@ -1,50 +0,0 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
A JSON Web Token (JWT) is used for authenticating and managing users in an application.
</p>
<p>
Using a hard-coded secret key for signing JWT tokens in open source projects
can leave the application using the token vulnerable to authentication bypasses.
</p>
<p>
A JWT token is safe for enforcing authentication and access control as long as it can't be forged by a malicious actor. However, when a project exposes this secret publicly, these seemingly unforgeable tokens can now be easily forged.
Since the authentication as well as access control is typically enforced through these JWT tokens, an attacker armed with the secret can create a valid authentication token for any user and may even gain access to other privileged parts of the application.
</p>
</overview>
<recommendation>
<p>
Generating a cryptographically secure secret key during application initialization and using this generated key for future JWT signing requests can prevent this vulnerability.
</p>
</recommendation>
<example>
<p>
The following code uses a hard-coded string as a secret for signing the tokens. In this case, an attacker can very easily forge a token by using the hard-coded secret.
</p>
<sample src="HardcodedKeysBad.go" />
</example>
<example>
<p>
In the following case, the application uses a programatically generated string as a secret for signing the tokens. In this case, since the secret can't be predicted, the code is secure. A function like `GenerateCryptoString` can be run to generate a secure secret key at the time of application installation/initialization. This generated key can then be used for all future signing requests.
</p>
<sample src="HardcodedKeysGood.go" />
</example>
<references>
<li>
CVE-2022-0664:
<a href="https://nvd.nist.gov/vuln/detail/CVE-2022-0664">Use of Hard-coded Cryptographic Key in Go github.com/gravitl/netmaker prior to 0.8.5,0.9.4,0.10.0,0.10.1. </a>
</li>
</references>
</qhelp>

View File

@@ -1,19 +0,0 @@
/**
* @name Use of a hardcoded key for signing JWT
* @description Using a fixed hardcoded key for signing JWT's can allow an attacker to compromise security.
* @kind path-problem
* @problem.severity error
* @id go/hardcoded-key
* @tags security
* experimental
* external/cwe/cwe-321
*/
import go
import HardcodedKeysLib
import HardcodedKeys::Flow::PathGraph
from HardcodedKeys::Flow::PathNode source, HardcodedKeys::Flow::PathNode sink
where HardcodedKeys::Flow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ is used to sign a JWT token.", source.getNode(),
"Hardcoded String"

View File

@@ -1,15 +0,0 @@
package main
import "time"
func bad() {
mySigningKey := []byte("AllYourBase")
claims := &jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Unix(1516239022, 0)),
Issuer: "test",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(mySigningKey)
}

View File

@@ -1,31 +0,0 @@
package main
import (
"math/big"
"time"
)
func GenerateCryptoString(n int) (string, error) {
const chars = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
ret := make([]byte, n)
for i := range ret {
num, err := crand.Int(crand.Reader, big.NewInt(int64(len(chars))))
if err != nil {
return "", err
}
ret[i] = chars[num.Int64()]
}
return string(ret), nil
}
func good() {
mySigningKey := GenerateCryptoString(64)
claims := &jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Unix(1516239022, 0)),
Issuer: "test",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(mySigningKey)
}

View File

@@ -1,389 +0,0 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* JWT token signing vulnerabilities as well as extension points
* for adding your own.
*/
import go
import StringOps
/**
* Provides default sources, sinks and sanitizers for reasoning about
* JWT token signing vulnerabilities as well as extension points
* for adding your own.
*/
module HardcodedKeys {
/**
* A data flow source for JWT token signing vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for JWT token signing vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for JWT token signing vulnerabilities.
*/
abstract class Sanitizer extends DataFlow::Node { }
private predicate isTestCode(Expr e) {
e.getFile().getAbsolutePath().toLowerCase().matches("%test%") and
not e.getFile().getAbsolutePath().toLowerCase().matches("%ql/test%")
}
private predicate isDemoCode(Expr e) {
e.getFile().getAbsolutePath().toLowerCase().matches(["%mock%", "%demo%", "%example%"])
}
/**
* A hardcoded string literal as a source for JWT token signing vulnerabilities.
*/
private class HardcodedStringSource extends Source {
HardcodedStringSource() {
this.asExpr() instanceof StringLit and
not (isTestCode(this.asExpr()) or isDemoCode(this.asExpr()))
}
}
/**
* An expression used to sign JWT tokens as a sink for JWT token signing vulnerabilities.
*/
private class GolangJwtSign extends Sink {
GolangJwtSign() {
exists(string pkg |
pkg =
[
"github.com/golang-jwt/jwt/v4", "github.com/dgrijalva/jwt-go",
"github.com/form3tech-oss/jwt-go", "github.com/ory/fosite/token/jwt"
]
|
exists(DataFlow::MethodCallNode m |
// Models the `SignedString` method
// `func (t *Token) SignedString(key interface{}) (string, error)`
m.getTarget().hasQualifiedName(pkg, "Token", "SignedString") and
this = m.getArgument(0)
or
// Model the `Sign` method of the `SigningMethod` interface
// type SigningMethod interface {
// Verify(signingString, signature string, key interface{}) error
// Sign(signingString string, key interface{}) (string, error)
// Alg() string
// }
m.getTarget().hasQualifiedName(pkg, "SigningMethod", "Sign") and
this = m.getArgument(1)
)
)
}
}
private class KatarasJwt extends Sink {
KatarasJwt() {
exists(string pkg |
pkg = package("github.com/kataras/jwt", "") and
(
exists(DataFlow::MethodCallNode m |
// Model the `Register` method of the type `Keys`
// func (keys Keys) Register(alg Alg, kid string, pubKey PublicKey, privKey PrivateKey)
m.getTarget().hasQualifiedName(pkg, "Keys", "Register")
|
this = m.getArgument(3)
)
or
exists(DataFlow::CallNode m, string names |
// Model the `Sign` method of the `SigningMethod` interface
// func Sign(alg Alg, key PrivateKey, claims interface{}, opts ...SignOption) ([]byte, error)
// func SignEncrypted(alg Alg, key PrivateKey, encrypt InjectFunc, claims interface{}, ...) ([]byte, error)
// func SignEncryptedWithHeader(alg Alg, key PrivateKey, encrypt InjectFunc, claims interface{}, ...) ([]byte, error)
// func SignWithHeader(alg Alg, key PrivateKey, claims interface{}, customHeader interface{}, ...) ([]byte, error)
m.getTarget().hasQualifiedName(pkg, names) and
names = ["Sign", "SignEncrypted", "SignEncryptedWithHeader", "SignWithHeader"]
|
this = m.getArgument(1)
)
)
)
}
}
private class IrisJwt extends Sink {
IrisJwt() {
exists(string pkg |
pkg = "github.com/kataras/iris/v12/middleware/jwt" and
(
exists(DataFlow::CallNode m |
//func NewSigner(signatureAlg Alg, signatureKey interface{}, maxAge time.Duration) *Signer
m.getTarget().hasQualifiedName(pkg, "NewSigner")
|
this = m.getArgument(1)
)
or
exists(Field f |
// Models the `key` field of the `Signer` type
// https://github.com/kataras/iris/blob/dccd57263617f5ca95d7621acfadf9dd37752dd6/middleware/jwt/signer.go#L17
f.hasQualifiedName(pkg, "Signer", "Key") and
f.getAWrite().getRhs() = this
)
)
)
}
}
private class GogfJwtSign extends Sink {
GogfJwtSign() {
exists(Field f, string pkg |
pkg = package("github.com/gogf/gf-jwt", "") and
// https://github.com/gogf/gf-jwt/blob/40503f05bc0a2bcd7aeba550163112afbb5c221f/auth_jwt.go#L27
f.hasQualifiedName(pkg, "GfJWTMiddleware", "Key") and
f.getAWrite().getRhs() = this
)
}
}
private class GinJwtSign extends Sink {
GinJwtSign() {
exists(Field f |
// https://pkg.go.dev/github.com/appleboy/gin-jwt/v2#GinJWTMiddleware
f.hasQualifiedName("github.com/appleboy/gin-jwt/v2", "GinJWTMiddleware", "Key") and
f.getAWrite().getRhs() = this
)
}
}
private class SquareJoseKey extends Sink {
SquareJoseKey() {
exists(Field f, string pkg |
// type Recipient struct {
// Algorithm KeyAlgorithm
// Key interface{}
// KeyID string
// PBES2Count int
// PBES2Salt []byte
// }
// type SigningKey struct {
// Algorithm SignatureAlgorithm
// Key interface{}
// }
f.hasQualifiedName(pkg, ["Recipient", "SigningKey"], "Key") and
f.getAWrite().getRhs() = this
|
pkg = ["github.com/square/go-jose/v3", "gopkg.in/square/go-jose.v2"]
)
}
}
private class CrystalHqJwtSigner extends Sink {
CrystalHqJwtSigner() {
exists(DataFlow::CallNode m |
// `func NewSignerHS(alg Algorithm, key []byte) (Signer, error)`
m.getTarget().hasQualifiedName("github.com/cristalhq/jwt/v3", "NewSignerHS")
|
this = m.getArgument(1)
)
}
}
private class GoKitJwt extends Sink {
GoKitJwt() {
exists(DataFlow::CallNode m |
// `func NewSigner(kid string, key []byte, method jwt.SigningMethod, claims jwt.Claims) endpoint.Middleware`
m.getTarget().hasQualifiedName("github.com/go-kit/kit/auth/jwt", "NewSigner")
|
this = m.getArgument(1)
)
}
}
private class LestrratJwk extends Sink {
LestrratJwk() {
exists(DataFlow::CallNode m, string pkg |
pkg.matches([
"github.com/lestrrat-go/jwx", "github.com/lestrrat/go-jwx/jwk",
"github.com/lestrrat-go/jwx%/jwk"
]) and
// `func New(key interface{}) (Key, error)`
m.getTarget().hasQualifiedName(pkg, "New")
|
this = m.getArgument(0)
)
}
}
/**
* Sanitizes any other use of an operand to a comparison, on the assumption that this may filter
* out special constant values -- for example, in context `if key != "invalid_key" { ... }`,
* if `"invalid_key"` is indeed the only dangerous key then guarded uses of `key` are likely
* to be safe.
*
* TODO: Before promoting this query look at replacing this with something more principled.
*/
private class CompareExprSanitizer extends Sanitizer {
CompareExprSanitizer() {
exists(ComparisonExpr c |
c.getAnOperand().getGlobalValueNumber() = this.asExpr().getGlobalValueNumber() and
not this.asExpr() instanceof Literal
)
}
}
/**
* Marks anything returned with an error as a sanitized.
*
* Typically this means contexts like `return "", errors.New("Oh no")`,
* where we can be reasonably confident downstream users won't mistake
* that empty string for a usable key.
*/
private class ReturnedAlongsideErrorSanitizer extends Sanitizer {
ReturnedAlongsideErrorSanitizer() {
exists(ReturnStmt r, DataFlow::CallNode c |
c.getTarget().hasQualifiedName("errors", "New") and
r.getNumChild() > 1 and
r.getAChild() = c.getAResult().getASuccessor*().asExpr() and
r.getAChild() = this.asExpr()
)
}
}
/**
* Marks anything returned alongside an error-value that is known
* to be non-nil by virtue of a guarding check as harmless.
*
* For example, `if err != nil { return "", err }` is unlikely to be
* contributing a dangerous hardcoded key.
*/
private class ReturnedAlongsideErrorSanitizerGuard extends Sanitizer {
ReturnedAlongsideErrorSanitizerGuard() {
exists(ControlFlow::ConditionGuardNode guard, SsaWithFields errorVar, ReturnStmt r |
guard.ensuresNeq(errorVar.getAUse(), Builtin::nil().getARead()) and
guard.dominates(this.getBasicBlock()) and
r.getExpr(1) = errorVar.getAUse().asExpr() and
this.asExpr() = r.getExpr(0)
)
}
}
/** Mark any formatting string call as a sanitizer */
private class FormattingSanitizer extends Sanitizer {
FormattingSanitizer() { exists(Formatting::StringFormatCall s | s.getAResult() = this) }
}
private string getRandIntFunctionName() {
result =
[
"ExpFloat64", "Float32", "Float64", "Int", "Int31", "Int31n", "Int63", "Int63n", "Intn",
"NormFloat64", "Uint32", "Uint64"
]
}
private DataFlow::CallNode getARandIntCall() {
result.getTarget().hasQualifiedName("math/rand", getRandIntFunctionName()) or
result.getTarget().(Method).hasQualifiedName("math/rand", "Rand", getRandIntFunctionName()) or
result.getTarget().hasQualifiedName("crypto/rand", "Int")
}
private DataFlow::CallNode getARandReadCall() {
result.getTarget().hasQualifiedName("crypto/rand", "Read")
}
/**
* Mark any taint arising from a read on a tainted slice with a random index as a
* sanitizer for all instances of the taint
*/
private class RandSliceSanitizer extends Sanitizer {
RandSliceSanitizer() {
exists(DataFlow::Node randomValue, DataFlow::Node index |
// Sanitize flows like this:
// func GenerateCryptoString(n int) (string, error) {
// const chars = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
// ret := make([]byte, n)
// for i := range ret {
// num, err := crand.Int(crand.Reader, big.NewInt(int64(len(chars))))
// if err != nil {
// return "", err
// }
// ret[i] = chars[num.Int64()]
// }
// return string(ret), nil
// }
randomValue = getARandIntCall().getAResult()
or
// Sanitize flows like :
// func GenerateRandomString(size int) string {
// var bytes = make([]byte, size)
// rand.Read(bytes)
// for i, x := range bytes {
// bytes[i] = characters[x%byte(len(characters))]
// }
// return string(bytes)
// }
randomValue =
any(DataFlow::PostUpdateNode pun |
pun.getPreUpdateNode() = getARandReadCall().getArgument(0)
)
|
TaintTracking::localTaint(randomValue, index) and
this.(DataFlow::ElementReadNode).reads(_, index)
)
}
}
/**
* Models flow from a call to `Int64` if the receiver is tainted
*/
private class BigIntFlow extends TaintTracking::FunctionModel {
BigIntFlow() { this.(Method).hasQualifiedName("math/big", "Int", "Int64") }
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
inp.isReceiver() and
outp.isResult(0)
}
}
/*
* Models taint flow through a binary operation such as a
* modulo `%` operation or an addition `+` operation
*/
private class BinExpAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
// This is required to model the sanitizers for the `HardcodedKeys` query.
// This is required to correctly detect a sanitizer such as the one shown below.
// func GenerateRandomString(size int) string {
// var bytes = make([]byte, size)
// rand.Read(bytes)
// for i, x := range bytes {
// bytes[i] = characters[x%byte(len(characters))]
// }
// return string(bytes)
// }
override predicate step(DataFlow::Node prev, DataFlow::Node succ) {
exists(BinaryExpr b | b.getAnOperand() = prev.asExpr() | succ.asExpr() = b)
}
}
/**
* DEPRECATED: Use `Flow` instead.
*
* A configuration depicting taint flow for studying JWT token signing vulnerabilities.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Hard-coded JWT Signing Key" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof Sanitizer }
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/** Tracks taint flow for reasoning about JWT token signing vulnerabilities. */
module Flow = TaintTracking::Global<Config>;
}

View File

@@ -1,126 +0,0 @@
edges
| HardcodedKeysBad.go:11:18:11:38 | type conversion | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | provenance | |
| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:11:18:11:38 | type conversion | provenance | |
| main.go:33:18:33:31 | type conversion | main.go:42:28:42:39 | mySigningKey | provenance | |
| main.go:33:25:33:30 | "key1" | main.go:33:18:33:31 | type conversion | provenance | |
| main.go:50:23:50:28 | "key2" | main.go:50:16:50:29 | type conversion | provenance | |
| main.go:68:9:68:22 | type conversion | main.go:69:44:69:46 | key | provenance | |
| main.go:68:16:68:21 | `key3` | main.go:68:9:68:22 | type conversion | provenance | |
| main.go:73:9:73:22 | type conversion | main.go:74:66:74:68 | key | provenance | |
| main.go:73:16:73:21 | "key4" | main.go:73:9:73:22 | type conversion | provenance | |
| main.go:77:10:77:23 | type conversion | main.go:82:15:82:18 | key2 | provenance | |
| main.go:77:17:77:22 | "key5" | main.go:77:10:77:23 | type conversion | provenance | |
| main.go:88:9:88:22 | type conversion | main.go:92:41:92:43 | key | provenance | |
| main.go:88:16:88:21 | "key6" | main.go:88:9:88:22 | type conversion | provenance | |
| main.go:97:10:97:23 | type conversion | main.go:99:66:99:69 | key2 | provenance | |
| main.go:97:17:97:22 | "key7" | main.go:97:10:97:23 | type conversion | provenance | |
| main.go:105:9:105:22 | type conversion | main.go:110:30:110:32 | key | provenance | |
| main.go:105:16:105:21 | "key8" | main.go:105:9:105:22 | type conversion | provenance | |
| main.go:114:15:114:28 | type conversion | main.go:115:16:115:24 | sharedKey | provenance | |
| main.go:114:22:114:27 | "key9" | main.go:114:15:114:28 | type conversion | provenance | |
| main.go:118:23:118:37 | type conversion | main.go:121:16:121:30 | sharedKeyglobal | provenance | |
| main.go:118:30:118:36 | "key10" | main.go:118:23:118:37 | type conversion | provenance | |
| main.go:127:27:127:33 | "key11" | main.go:127:20:127:34 | type conversion | provenance | |
| main.go:142:14:142:28 | type conversion | main.go:144:39:144:46 | mySecret | provenance | |
| main.go:142:21:142:27 | "key12" | main.go:142:14:142:28 | type conversion | provenance | |
| main.go:149:14:149:28 | type conversion | main.go:153:11:153:18 | mySecret | provenance | |
| main.go:149:21:149:27 | "key13" | main.go:149:14:149:28 | type conversion | provenance | |
| main.go:160:12:160:26 | type conversion | main.go:161:34:161:39 | secret | provenance | |
| main.go:160:19:160:25 | "key14" | main.go:160:12:160:26 | type conversion | provenance | |
| main.go:166:12:166:26 | type conversion | main.go:167:32:167:37 | secret | provenance | |
| main.go:166:19:166:25 | "key15" | main.go:166:12:166:26 | type conversion | provenance | |
| main.go:172:12:172:26 | type conversion | main.go:173:41:173:46 | secret | provenance | |
| main.go:172:19:172:25 | "key16" | main.go:172:12:172:26 | type conversion | provenance | |
| main.go:178:12:178:26 | type conversion | main.go:179:51:179:56 | secret | provenance | |
| main.go:178:19:178:25 | "key17" | main.go:178:12:178:26 | type conversion | provenance | |
| main.go:184:12:184:26 | type conversion | main.go:185:42:185:47 | secret | provenance | |
| main.go:184:19:184:25 | "key18" | main.go:184:12:184:26 | type conversion | provenance | |
| main.go:190:12:190:26 | type conversion | main.go:193:33:193:38 | secret | provenance | |
| main.go:190:19:190:25 | "key19" | main.go:190:12:190:26 | type conversion | provenance | |
| sanitizer.go:17:9:17:21 | type conversion | sanitizer.go:18:44:18:46 | key | provenance | |
| sanitizer.go:17:16:17:20 | `key` | sanitizer.go:17:9:17:21 | type conversion | provenance | |
nodes
| HardcodedKeysBad.go:11:18:11:38 | type conversion | semmle.label | type conversion |
| HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | semmle.label | "AllYourBase" |
| HardcodedKeysBad.go:19:28:19:39 | mySigningKey | semmle.label | mySigningKey |
| main.go:33:18:33:31 | type conversion | semmle.label | type conversion |
| main.go:33:25:33:30 | "key1" | semmle.label | "key1" |
| main.go:42:28:42:39 | mySigningKey | semmle.label | mySigningKey |
| main.go:50:16:50:29 | type conversion | semmle.label | type conversion |
| main.go:50:23:50:28 | "key2" | semmle.label | "key2" |
| main.go:68:9:68:22 | type conversion | semmle.label | type conversion |
| main.go:68:16:68:21 | `key3` | semmle.label | `key3` |
| main.go:69:44:69:46 | key | semmle.label | key |
| main.go:73:9:73:22 | type conversion | semmle.label | type conversion |
| main.go:73:16:73:21 | "key4" | semmle.label | "key4" |
| main.go:74:66:74:68 | key | semmle.label | key |
| main.go:77:10:77:23 | type conversion | semmle.label | type conversion |
| main.go:77:17:77:22 | "key5" | semmle.label | "key5" |
| main.go:82:15:82:18 | key2 | semmle.label | key2 |
| main.go:88:9:88:22 | type conversion | semmle.label | type conversion |
| main.go:88:16:88:21 | "key6" | semmle.label | "key6" |
| main.go:92:41:92:43 | key | semmle.label | key |
| main.go:97:10:97:23 | type conversion | semmle.label | type conversion |
| main.go:97:17:97:22 | "key7" | semmle.label | "key7" |
| main.go:99:66:99:69 | key2 | semmle.label | key2 |
| main.go:105:9:105:22 | type conversion | semmle.label | type conversion |
| main.go:105:16:105:21 | "key8" | semmle.label | "key8" |
| main.go:110:30:110:32 | key | semmle.label | key |
| main.go:114:15:114:28 | type conversion | semmle.label | type conversion |
| main.go:114:22:114:27 | "key9" | semmle.label | "key9" |
| main.go:115:16:115:24 | sharedKey | semmle.label | sharedKey |
| main.go:118:23:118:37 | type conversion | semmle.label | type conversion |
| main.go:118:30:118:36 | "key10" | semmle.label | "key10" |
| main.go:121:16:121:30 | sharedKeyglobal | semmle.label | sharedKeyglobal |
| main.go:127:20:127:34 | type conversion | semmle.label | type conversion |
| main.go:127:27:127:33 | "key11" | semmle.label | "key11" |
| main.go:142:14:142:28 | type conversion | semmle.label | type conversion |
| main.go:142:21:142:27 | "key12" | semmle.label | "key12" |
| main.go:144:39:144:46 | mySecret | semmle.label | mySecret |
| main.go:149:14:149:28 | type conversion | semmle.label | type conversion |
| main.go:149:21:149:27 | "key13" | semmle.label | "key13" |
| main.go:153:11:153:18 | mySecret | semmle.label | mySecret |
| main.go:160:12:160:26 | type conversion | semmle.label | type conversion |
| main.go:160:19:160:25 | "key14" | semmle.label | "key14" |
| main.go:161:34:161:39 | secret | semmle.label | secret |
| main.go:166:12:166:26 | type conversion | semmle.label | type conversion |
| main.go:166:19:166:25 | "key15" | semmle.label | "key15" |
| main.go:167:32:167:37 | secret | semmle.label | secret |
| main.go:172:12:172:26 | type conversion | semmle.label | type conversion |
| main.go:172:19:172:25 | "key16" | semmle.label | "key16" |
| main.go:173:41:173:46 | secret | semmle.label | secret |
| main.go:178:12:178:26 | type conversion | semmle.label | type conversion |
| main.go:178:19:178:25 | "key17" | semmle.label | "key17" |
| main.go:179:51:179:56 | secret | semmle.label | secret |
| main.go:184:12:184:26 | type conversion | semmle.label | type conversion |
| main.go:184:19:184:25 | "key18" | semmle.label | "key18" |
| main.go:185:42:185:47 | secret | semmle.label | secret |
| main.go:190:12:190:26 | type conversion | semmle.label | type conversion |
| main.go:190:19:190:25 | "key19" | semmle.label | "key19" |
| main.go:193:33:193:38 | secret | semmle.label | secret |
| sanitizer.go:17:9:17:21 | type conversion | semmle.label | type conversion |
| sanitizer.go:17:16:17:20 | `key` | semmle.label | `key` |
| sanitizer.go:18:44:18:46 | key | semmle.label | key |
subpaths
#select
| HardcodedKeysBad.go:19:28:19:39 | mySigningKey | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | $@ is used to sign a JWT token. | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | Hardcoded String |
| main.go:42:28:42:39 | mySigningKey | main.go:33:25:33:30 | "key1" | main.go:42:28:42:39 | mySigningKey | $@ is used to sign a JWT token. | main.go:33:25:33:30 | "key1" | Hardcoded String |
| main.go:50:16:50:29 | type conversion | main.go:50:23:50:28 | "key2" | main.go:50:16:50:29 | type conversion | $@ is used to sign a JWT token. | main.go:50:23:50:28 | "key2" | Hardcoded String |
| main.go:69:44:69:46 | key | main.go:68:16:68:21 | `key3` | main.go:69:44:69:46 | key | $@ is used to sign a JWT token. | main.go:68:16:68:21 | `key3` | Hardcoded String |
| main.go:74:66:74:68 | key | main.go:73:16:73:21 | "key4" | main.go:74:66:74:68 | key | $@ is used to sign a JWT token. | main.go:73:16:73:21 | "key4" | Hardcoded String |
| main.go:82:15:82:18 | key2 | main.go:77:17:77:22 | "key5" | main.go:82:15:82:18 | key2 | $@ is used to sign a JWT token. | main.go:77:17:77:22 | "key5" | Hardcoded String |
| main.go:92:41:92:43 | key | main.go:88:16:88:21 | "key6" | main.go:92:41:92:43 | key | $@ is used to sign a JWT token. | main.go:88:16:88:21 | "key6" | Hardcoded String |
| main.go:99:66:99:69 | key2 | main.go:97:17:97:22 | "key7" | main.go:99:66:99:69 | key2 | $@ is used to sign a JWT token. | main.go:97:17:97:22 | "key7" | Hardcoded String |
| main.go:110:30:110:32 | key | main.go:105:16:105:21 | "key8" | main.go:110:30:110:32 | key | $@ is used to sign a JWT token. | main.go:105:16:105:21 | "key8" | Hardcoded String |
| main.go:115:16:115:24 | sharedKey | main.go:114:22:114:27 | "key9" | main.go:115:16:115:24 | sharedKey | $@ is used to sign a JWT token. | main.go:114:22:114:27 | "key9" | Hardcoded String |
| main.go:121:16:121:30 | sharedKeyglobal | main.go:118:30:118:36 | "key10" | main.go:121:16:121:30 | sharedKeyglobal | $@ is used to sign a JWT token. | main.go:118:30:118:36 | "key10" | Hardcoded String |
| main.go:127:20:127:34 | type conversion | main.go:127:27:127:33 | "key11" | main.go:127:20:127:34 | type conversion | $@ is used to sign a JWT token. | main.go:127:27:127:33 | "key11" | Hardcoded String |
| main.go:144:39:144:46 | mySecret | main.go:142:21:142:27 | "key12" | main.go:144:39:144:46 | mySecret | $@ is used to sign a JWT token. | main.go:142:21:142:27 | "key12" | Hardcoded String |
| main.go:153:11:153:18 | mySecret | main.go:149:21:149:27 | "key13" | main.go:153:11:153:18 | mySecret | $@ is used to sign a JWT token. | main.go:149:21:149:27 | "key13" | Hardcoded String |
| main.go:161:34:161:39 | secret | main.go:160:19:160:25 | "key14" | main.go:161:34:161:39 | secret | $@ is used to sign a JWT token. | main.go:160:19:160:25 | "key14" | Hardcoded String |
| main.go:167:32:167:37 | secret | main.go:166:19:166:25 | "key15" | main.go:167:32:167:37 | secret | $@ is used to sign a JWT token. | main.go:166:19:166:25 | "key15" | Hardcoded String |
| main.go:173:41:173:46 | secret | main.go:172:19:172:25 | "key16" | main.go:173:41:173:46 | secret | $@ is used to sign a JWT token. | main.go:172:19:172:25 | "key16" | Hardcoded String |
| main.go:179:51:179:56 | secret | main.go:178:19:178:25 | "key17" | main.go:179:51:179:56 | secret | $@ is used to sign a JWT token. | main.go:178:19:178:25 | "key17" | Hardcoded String |
| main.go:185:42:185:47 | secret | main.go:184:19:184:25 | "key18" | main.go:185:42:185:47 | secret | $@ is used to sign a JWT token. | main.go:184:19:184:25 | "key18" | Hardcoded String |
| main.go:193:33:193:38 | secret | main.go:190:19:190:25 | "key19" | main.go:193:33:193:38 | secret | $@ is used to sign a JWT token. | main.go:190:19:190:25 | "key19" | Hardcoded String |
| sanitizer.go:18:44:18:46 | key | sanitizer.go:17:16:17:20 | `key` | sanitizer.go:18:44:18:46 | key | $@ is used to sign a JWT token. | sanitizer.go:17:16:17:20 | `key` | Hardcoded String |

View File

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

View File

@@ -1,7 +1,28 @@
| AlertSuppressionExample.go:11:14:11:40 | "horsebatterystaplecorrect" | Hard-coded $@. | AlertSuppressionExample.go:11:14:11:40 | "horsebatterystaplecorrect" | password |
| HardcodedCredentials.go:10:13:10:28 | "s3cretp4ssword" | Hard-coded $@. | HardcodedCredentials.go:10:13:10:28 | "s3cretp4ssword" | password |
| HardcodedKeysBad.go:19:28:19:39 | mySigningKey | Hard-coded credential. | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | password |
| jwt.go:42:28:42:39 | mySigningKey | Hard-coded credential. | jwt.go:33:25:33:30 | "key1" | password |
| jwt.go:49:16:49:29 | type conversion | Hard-coded credential. | jwt.go:49:23:49:28 | "key2" | password |
| jwt.go:68:44:68:46 | key | Hard-coded credential. | jwt.go:67:16:67:21 | `key3` | password |
| jwt.go:73:66:73:68 | key | Hard-coded credential. | jwt.go:72:16:72:21 | "key4" | password |
| jwt.go:81:15:81:18 | key2 | Hard-coded credential. | jwt.go:76:17:76:22 | "key5" | password |
| jwt.go:91:41:91:43 | key | Hard-coded credential. | jwt.go:87:16:87:21 | "key6" | password |
| jwt.go:98:66:98:69 | key2 | Hard-coded credential. | jwt.go:96:17:96:22 | "key7" | password |
| jwt.go:109:30:109:32 | key | Hard-coded credential. | jwt.go:104:16:104:21 | "key8" | password |
| jwt.go:114:16:114:24 | sharedKey | Hard-coded credential. | jwt.go:113:22:113:27 | "key9" | password |
| jwt.go:120:16:120:30 | sharedKeyglobal | Hard-coded credential. | jwt.go:117:30:117:36 | "key10" | password |
| jwt.go:126:20:126:34 | type conversion | Hard-coded credential. | jwt.go:126:27:126:33 | "key11" | password |
| jwt.go:143:39:143:46 | safeName | Hard-coded credential. | jwt.go:141:21:141:27 | "key12" | password |
| jwt.go:152:11:152:18 | safeName | Hard-coded credential. | jwt.go:148:21:148:27 | "key13" | password |
| jwt.go:160:34:160:41 | safeName | Hard-coded credential. | jwt.go:159:21:159:27 | "key14" | password |
| jwt.go:166:32:166:39 | safeName | Hard-coded credential. | jwt.go:165:21:165:27 | "key15" | password |
| jwt.go:172:41:172:48 | safeName | Hard-coded credential. | jwt.go:171:21:171:27 | "key16" | password |
| jwt.go:178:51:178:58 | safeName | Hard-coded credential. | jwt.go:177:21:177:27 | "key17" | password |
| jwt.go:184:42:184:49 | safeName | Hard-coded credential. | jwt.go:183:21:183:27 | "key18" | password |
| jwt.go:192:33:192:40 | safeName | Hard-coded credential. | jwt.go:189:21:189:27 | "key19" | password |
| main.go:6:14:6:23 | "p4ssw0rd" | Hard-coded $@. | main.go:6:14:6:23 | "p4ssw0rd" | password |
| main.go:12:1:26:30 | `-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQC/tzdtXKXcX6F3v3hR6+uYyZpIeXhhLflJkY2eILLQfAnwKlT5\nxIHW5QZcHQV9sCyZ8qSdPGif7PwgMbButMbByiZhCSugUFb6vjVqoktmslYF4LKH\niDgvmlwuJW0TvynxBLzDCwrRP+gpRT8wuAortWAx/03POTw7Mzi2cIPNsQIDAQAB\nAoGAMHCrqY9CPTdQhgAz94cDpTwzJmLCvtMt7J/BR5X9eF4O6MbZZ652HAUMIVQX\n4hUUf+VmIHB2AwqO/ddwO9ijaz04BslOSy/iYevHGlH65q4587NSlFWjvILMIQCM\nGBjfzJIxlLHVhjc2cFnyAE5YWjF/OMnJN0OhP9pxmCP/iM0CQQDxmQndQLdnV7+6\n8SvBHE8bg1LE8/BzTt68U3aWwiBjrHMFgzr//7Za4VF7h4ilFgmbh0F3sYz+C8iO\n0JrBRPeLAkEAyyTwnv/pgqTS/wuxIHUxRBpbdk3YvILAthNrGQg5uzA7eSeFu7Mv\nGtEkXsaqCDbdehgarFfNN8PB6OMRIbsXMwJBAOjhH8UJ0L/osYO9XPO0GfznRS1c\nBnbfm4vk1/bSAO6TF/xEVubU0i4f6q8sIecfqvskEVMS7lkjeptPMR0DIakCQE+7\nuQH/Wizf+r0GXshplyOu4LVHisk63N7aMlAJ7XbuUHmWLKRmiReSfR8CBNzig/2X\nFmkMsUyw9hwte5zsrQcCQQCrOkZvzUj9j1HKG+32EJ2E4kisJZmAgF9GI+z6oxpi\nExped5tp8EWytCjRwKhOcc0068SgaqhKvyyUWpbx32VQ\n-----END RSA PRIVATE KEY-----` | Hard-coded private key. | main.go:12:1:26:30 | `-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQC/tzdtXKXcX6F3v3hR6+uYyZpIeXhhLflJkY2eILLQfAnwKlT5\nxIHW5QZcHQV9sCyZ8qSdPGif7PwgMbButMbByiZhCSugUFb6vjVqoktmslYF4LKH\niDgvmlwuJW0TvynxBLzDCwrRP+gpRT8wuAortWAx/03POTw7Mzi2cIPNsQIDAQAB\nAoGAMHCrqY9CPTdQhgAz94cDpTwzJmLCvtMt7J/BR5X9eF4O6MbZZ652HAUMIVQX\n4hUUf+VmIHB2AwqO/ddwO9ijaz04BslOSy/iYevHGlH65q4587NSlFWjvILMIQCM\nGBjfzJIxlLHVhjc2cFnyAE5YWjF/OMnJN0OhP9pxmCP/iM0CQQDxmQndQLdnV7+6\n8SvBHE8bg1LE8/BzTt68U3aWwiBjrHMFgzr//7Za4VF7h4ilFgmbh0F3sYz+C8iO\n0JrBRPeLAkEAyyTwnv/pgqTS/wuxIHUxRBpbdk3YvILAthNrGQg5uzA7eSeFu7Mv\nGtEkXsaqCDbdehgarFfNN8PB6OMRIbsXMwJBAOjhH8UJ0L/osYO9XPO0GfznRS1c\nBnbfm4vk1/bSAO6TF/xEVubU0i4f6q8sIecfqvskEVMS7lkjeptPMR0DIakCQE+7\nuQH/Wizf+r0GXshplyOu4LVHisk63N7aMlAJ7XbuUHmWLKRmiReSfR8CBNzig/2X\nFmkMsUyw9hwte5zsrQcCQQCrOkZvzUj9j1HKG+32EJ2E4kisJZmAgF9GI+z6oxpi\nExped5tp8EWytCjRwKhOcc0068SgaqhKvyyUWpbx32VQ\n-----END RSA PRIVATE KEY-----` | certificate |
| main.go:44:14:44:19 | "p4ss" | Hard-coded $@. | main.go:44:14:44:19 | "p4ss" | password |
| main.go:48:13:48:15 | tmp | Hard-coded $@. | main.go:44:14:44:19 | "p4ss" | password |
| main.go:50:15:50:21 | "p4ss2" | Hard-coded $@. | main.go:50:15:50:21 | "p4ss2" | password |
| sanitizer.go:18:44:18:46 | key | Hard-coded credential. | sanitizer.go:17:16:17:20 | `key` | password |

View File

@@ -44,7 +44,6 @@ func gjwtt() (interface{}, error) {
func gin_jwt() (interface{}, error) {
var identityKey = "id"
// authMiddleware, err :=
return jwt.New(&jwt.GinJWTMiddleware{
Realm: "test zone",
Key: []byte("key2"), // BAD
@@ -124,7 +123,7 @@ func lejwt2() (interface{}, error) {
func gogfjwt() interface{} {
return &gogf.GfJWTMiddleware{
Realm: "test zone",
Key: []byte("key11"),
Key: []byte("key11"), // BAD
Timeout: time.Minute * 5,
MaxRefresh: time.Minute * 5,
IdentityKey: "id",
@@ -139,58 +138,58 @@ func gogfjwt() interface{} {
}
func irisjwt() interface{} {
mySecret := []byte("key12")
safeName := []byte("key12")
token := iris.NewTokenWithClaims(nil, nil)
tokenString, _ := token.SignedString(mySecret)
tokenString, _ := token.SignedString(safeName) // BAD
return tokenString
}
func iris12jwt2() interface{} {
mySecret := []byte("key13")
safeName := []byte("key13")
s := &iris12.Signer{
Alg: nil,
Key: mySecret,
Key: safeName, // BAD
MaxAge: 3 * time.Second,
}
return s
}
func irisjwt3() interface{} {
secret := []byte("key14")
signer := iris12.NewSigner(nil, secret, 3*time.Second)
safeName := []byte("key14")
signer := iris12.NewSigner(nil, safeName, 3*time.Second) // BAD
return signer
}
func katarasJwt() interface{} {
secret := []byte("key15")
token, _ := kataras.Sign(nil, secret, nil, nil)
safeName := []byte("key15")
token, _ := kataras.Sign(nil, safeName, nil, nil) // BAD
return token
}
func katarasJwt2() interface{} {
secret := []byte("key16")
token, _ := kataras.SignEncrypted(nil, secret, nil, nil)
safeName := []byte("key16")
token, _ := kataras.SignEncrypted(nil, safeName, nil, nil) // BAD
return token
}
func katarasJwt3() interface{} {
secret := []byte("key17")
token, _ := kataras.SignEncryptedWithHeader(nil, secret, nil, nil, nil)
safeName := []byte("key17")
token, _ := kataras.SignEncryptedWithHeader(nil, safeName, nil, nil, nil) // BAD
return token
}
func katarasJwt4() interface{} {
secret := []byte("key18")
token, _ := kataras.SignWithHeader(nil, secret, nil, nil)
safeName := []byte("key18")
token, _ := kataras.SignWithHeader(nil, safeName, nil, nil) // BAD
return token
}
func katarasJwt5() {
secret := []byte("key19")
safeName := []byte("key19")
var keys kataras.Keys
var alg kataras.Alg
keys.Register(alg, "api", nil, secret)
keys.Register(alg, "api", nil, safeName) // BAD
}
func main() {