Merge pull request #15527 from atorralba/atorralba/go/promote-hardcoded-key

Go: Promote `go/hardcoded-key` from experimental
This commit is contained in:
Tony Torralba
2024-02-14 16:54:03 +01:00
committed by GitHub
47 changed files with 353 additions and 665 deletions

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/cristalhq/jwt", "", 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", "", 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", "Token", True, "SignedString", "", "", "Argument[0]", "credentials-key", "manual"]
- ["github.com/golang-jwt/jwt", "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

@@ -45,6 +45,8 @@ import semmle.go.frameworks.Fiber
import semmle.go.frameworks.Gin
import semmle.go.frameworks.GinCors
import semmle.go.frameworks.Glog
import semmle.go.frameworks.Gogf
import semmle.go.frameworks.GoJose
import semmle.go.frameworks.GoKit
import semmle.go.frameworks.GoMicro
import semmle.go.frameworks.GoRestfulHttp

View File

@@ -1,8 +1,9 @@
/**
* Provides classes for working with untrusted flow sources from the `github.com/gin-gonic/gin` package.
* Provides classes for working with the `github.com/gin-gonic/gin` package.
*/
import go
private import semmle.go.security.HardcodedCredentials
private module Gin {
/** Gets the package name `github.com/gin-gonic/gin`. */
@@ -75,4 +76,13 @@ private module Gin {
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
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
)
}
}
}

View File

@@ -0,0 +1,24 @@
/**
* Provides classes for working with the `github.com/square/go-jose`, `github.com/go-jose/go-jose`,
* and `gopkg.in/square-go-jose.v2` packages.
*/
import go
private import semmle.go.security.HardcodedCredentials
private module GoJose {
private class GoJoseKey extends HardcodedCredentials::Sink {
GoJoseKey() {
exists(Field f, string pkg |
pkg =
[
package("github.com/square/go-jose", ""), package("github.com/go-jose/go-jose", ""),
"gopkg.in/square/go-jose.v2"
]
|
f.hasQualifiedName(pkg, ["Recipient", "SigningKey"], "Key") and
f.getAWrite().getRhs() = this
)
}
}
}

View File

@@ -0,0 +1,17 @@
/**
* Provides classes for working the `github.com/gogf` package.
*/
import go
private import semmle.go.security.HardcodedCredentials
private module Gogf {
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
)
}
}
}

View File

@@ -3,6 +3,7 @@
*/
import go
private import semmle.go.security.HardcodedCredentials
private module Iris {
/** Gets the v1 module path `github.com/kataras/iris`. */
@@ -46,4 +47,13 @@ private module Iris {
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
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
)
}
}
}

View File

@@ -0,0 +1,137 @@
/**
* 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.SensitiveActions
/**
* 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() {
exists(StringLit val | this.asExpr() = val |
not PasswordHeuristics::isDummyPassword(val.getStringValue())
)
}
}
/** 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 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 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 ReturnedWithErrorSanitizer extends Sanitizer {
ReturnedWithErrorSanitizer() { DataFlow::isReturnedWithError(this) }
}
/** 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

@@ -14,6 +14,7 @@
*/
import go
import semmle.go.security.HardcodedCredentials
import semmle.go.security.SensitiveActions
/**
@@ -31,22 +32,34 @@ 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
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:25 | `some_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,60 +138,56 @@ 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)
}
func main() {
return
keys.Register(alg, "api", nil, safeName) // BAD
}

View File

@@ -14,7 +14,7 @@ import (
)
func check_ok() (interface{}, error) {
key := []byte(`key`)
key := []byte(`some_key`)
return cristal.NewSignerHS(cristal.HS256, key) // BAD
}