mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Split up hardcoded creds queries, ready for conversion to inline expectations
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Provides a data-flow configuration for tracking a hard-coded credential in a call to a sensitive Java API which may compromise security.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.DataFlow
|
||||||
|
import HardcodedCredentials
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks flow from a hard-coded credential in a call to a sensitive Java API which may compromise security.
|
||||||
|
*/
|
||||||
|
class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration {
|
||||||
|
HardcodedCredentialApiCallConfiguration() { this = "HardcodedCredentialApiCallConfiguration" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node n) {
|
||||||
|
n.asExpr() instanceof HardcodedExpr and
|
||||||
|
not n.asExpr().getEnclosingCallable() instanceof ToStringMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink }
|
||||||
|
|
||||||
|
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
node1.asExpr().getType() instanceof TypeString and
|
||||||
|
(
|
||||||
|
exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) |
|
||||||
|
node2.asExpr() = ma and
|
||||||
|
ma.getQualifier() = node1.asExpr()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// These base64 routines are usually taint propagators, and this is not a general
|
||||||
|
// TaintTracking::Configuration, so we must specifically include them here
|
||||||
|
// as a common transform applied to a constant before passing to a remote API.
|
||||||
|
exists(MethodAccess ma |
|
||||||
|
ma.getMethod()
|
||||||
|
.hasQualifiedName([
|
||||||
|
"java.util", "cn.hutool.core.codec", "org.apache.shiro.codec",
|
||||||
|
"apache.commons.codec.binary", "org.springframework.util"
|
||||||
|
], ["Base64$Encoder", "Base64$Decoder", "Base64", "Base64Utils"],
|
||||||
|
[
|
||||||
|
"encode", "encodeToString", "decode", "decodeBase64", "encodeBase64",
|
||||||
|
"encodeBase64Chunked", "encodeBase64String", "encodeBase64URLSafe",
|
||||||
|
"encodeBase64URLSafeString"
|
||||||
|
])
|
||||||
|
|
|
||||||
|
node1.asExpr() = ma.getArgument(0) and
|
||||||
|
node2.asExpr() = ma
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isBarrier(DataFlow::Node n) {
|
||||||
|
n.asExpr().(MethodAccess).getMethod() instanceof MethodSystemGetenv
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes and predicates to detect comparing a parameter to a hard-coded credential.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import HardcodedCredentials
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A call to a method that is or overrides `java.lang.Object.equals`.
|
||||||
|
*/
|
||||||
|
class EqualsAccess extends MethodAccess {
|
||||||
|
EqualsAccess() { getMethod() instanceof EqualsMethod }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `sink` compares password `p` against a hardcoded expression `source`.
|
||||||
|
*/
|
||||||
|
predicate isHardcodedCredentialsComparison(
|
||||||
|
EqualsAccess sink, HardcodedExpr source, PasswordVariable p
|
||||||
|
) {
|
||||||
|
source = sink.getQualifier() and
|
||||||
|
p.getAnAccess() = sink.getArgument(0)
|
||||||
|
or
|
||||||
|
source = sink.getArgument(0) and
|
||||||
|
p.getAnAccess() = sink.getQualifier()
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes to detect using a hard-coded credential in a sensitive call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.DataFlow
|
||||||
|
import semmle.code.java.dataflow.DataFlow2
|
||||||
|
import HardcodedCredentials
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data-flow configuration that tracks hardcoded expressions flowing to a parameter whose name suggests
|
||||||
|
* it may be a credential, excluding those which flow on to other such insecure usage sites.
|
||||||
|
*/
|
||||||
|
class HardcodedCredentialSourceCallConfiguration extends DataFlow::Configuration {
|
||||||
|
HardcodedCredentialSourceCallConfiguration() {
|
||||||
|
this = "HardcodedCredentialSourceCallConfiguration"
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof HardcodedExpr }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof FinalCredentialsSourceSink }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data-flow configuration that tracks flow from an argument whose corresponding parameter name suggests
|
||||||
|
* a credential, to an argument to a sensitive call.
|
||||||
|
*/
|
||||||
|
class HardcodedCredentialSourceCallConfiguration2 extends DataFlow2::Configuration {
|
||||||
|
HardcodedCredentialSourceCallConfiguration2() {
|
||||||
|
this = "HardcodedCredentialSourceCallConfiguration2"
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof CredentialsSourceSink }
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsSink }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An argument to a call, where the parameter name corresponding
|
||||||
|
* to the argument indicates that it may contain credentials, and
|
||||||
|
* where this expression does not flow on to another `CredentialsSink`.
|
||||||
|
*/
|
||||||
|
class FinalCredentialsSourceSink extends CredentialsSourceSink {
|
||||||
|
FinalCredentialsSourceSink() {
|
||||||
|
not exists(HardcodedCredentialSourceCallConfiguration2 conf, CredentialsSink other |
|
||||||
|
this != other
|
||||||
|
|
|
||||||
|
conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(other))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Provides a predicate identifying assignments of harcoded values to password fields.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import HardcodedCredentials
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if non-empty constant value `e` is assigned to password field `f`.
|
||||||
|
*/
|
||||||
|
predicate passwordFieldAssignedHardcodedValue(PasswordVariable f, CompileTimeConstantExpr e) {
|
||||||
|
f instanceof Field and
|
||||||
|
f.getAnAssignedValue() = e and
|
||||||
|
not e.(StringLiteral).getValue() = ""
|
||||||
|
}
|
||||||
@@ -10,55 +10,9 @@
|
|||||||
* external/cwe/cwe-798
|
* external/cwe/cwe-798
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import semmle.code.java.security.HardcodedCredentialsApiCallQuery
|
||||||
import semmle.code.java.dataflow.DataFlow
|
|
||||||
import HardcodedCredentials
|
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration {
|
|
||||||
HardcodedCredentialApiCallConfiguration() { this = "HardcodedCredentialApiCallConfiguration" }
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node n) {
|
|
||||||
n.asExpr() instanceof HardcodedExpr and
|
|
||||||
not n.asExpr().getEnclosingCallable() instanceof ToStringMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink }
|
|
||||||
|
|
||||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
node1.asExpr().getType() instanceof TypeString and
|
|
||||||
(
|
|
||||||
exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) |
|
|
||||||
node2.asExpr() = ma and
|
|
||||||
ma.getQualifier() = node1.asExpr()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// These base64 routines are usually taint propagators, and this is not a general
|
|
||||||
// TaintTracking::Configuration, so we must specifically include them here
|
|
||||||
// as a common transform applied to a constant before passing to a remote API.
|
|
||||||
exists(MethodAccess ma |
|
|
||||||
ma.getMethod()
|
|
||||||
.hasQualifiedName([
|
|
||||||
"java.util", "cn.hutool.core.codec", "org.apache.shiro.codec",
|
|
||||||
"apache.commons.codec.binary", "org.springframework.util"
|
|
||||||
], ["Base64$Encoder", "Base64$Decoder", "Base64", "Base64Utils"],
|
|
||||||
[
|
|
||||||
"encode", "encodeToString", "decode", "decodeBase64", "encodeBase64",
|
|
||||||
"encodeBase64Chunked", "encodeBase64String", "encodeBase64URLSafe",
|
|
||||||
"encodeBase64URLSafeString"
|
|
||||||
])
|
|
||||||
|
|
|
||||||
node1.asExpr() = ma.getArgument(0) and
|
|
||||||
node2.asExpr() = ma
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isBarrier(DataFlow::Node n) {
|
|
||||||
n.asExpr().(MethodAccess).getMethod() instanceof MethodSystemGetenv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedCredentialApiCallConfiguration conf
|
DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedCredentialApiCallConfiguration conf
|
||||||
where conf.hasFlowPath(source, sink)
|
where conf.hasFlowPath(source, sink)
|
||||||
|
|||||||
@@ -11,17 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import HardcodedCredentials
|
import semmle.code.java.security.HardcodedCredentialsComparison
|
||||||
|
|
||||||
class EqualsAccess extends MethodAccess {
|
|
||||||
EqualsAccess() { getMethod() instanceof EqualsMethod }
|
|
||||||
}
|
|
||||||
|
|
||||||
from EqualsAccess sink, HardcodedExpr source, PasswordVariable p
|
from EqualsAccess sink, HardcodedExpr source, PasswordVariable p
|
||||||
where
|
where isHardcodedCredentialsComparison(sink, source, p)
|
||||||
source = sink.getQualifier() and
|
|
||||||
p.getAnAccess() = sink.getArgument(0)
|
|
||||||
or
|
|
||||||
source = sink.getArgument(0) and
|
|
||||||
p.getAnAccess() = sink.getQualifier()
|
|
||||||
select source, "Hard-coded value is $@ with password variable $@.", sink, "compared", p, p.getName()
|
select source, "Hard-coded value is $@ with password variable $@.", sink, "compared", p, p.getName()
|
||||||
|
|||||||
@@ -11,41 +11,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.DataFlow
|
import semmle.code.java.security.HardcodedCredentialsSourceCall
|
||||||
import semmle.code.java.dataflow.DataFlow2
|
|
||||||
import HardcodedCredentials
|
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
class HardcodedCredentialSourceCallConfiguration extends DataFlow::Configuration {
|
|
||||||
HardcodedCredentialSourceCallConfiguration() {
|
|
||||||
this = "HardcodedCredentialSourceCallConfiguration"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof HardcodedExpr }
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof FinalCredentialsSourceSink }
|
|
||||||
}
|
|
||||||
|
|
||||||
class HardcodedCredentialSourceCallConfiguration2 extends DataFlow2::Configuration {
|
|
||||||
HardcodedCredentialSourceCallConfiguration2() {
|
|
||||||
this = "HardcodedCredentialSourceCallConfiguration2"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node n) { n.asExpr() instanceof CredentialsSourceSink }
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsSink }
|
|
||||||
}
|
|
||||||
|
|
||||||
class FinalCredentialsSourceSink extends CredentialsSourceSink {
|
|
||||||
FinalCredentialsSourceSink() {
|
|
||||||
not exists(HardcodedCredentialSourceCallConfiguration2 conf, CredentialsSink other |
|
|
||||||
this != other
|
|
||||||
|
|
|
||||||
conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(other))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink,
|
DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||||
HardcodedCredentialSourceCallConfiguration conf
|
HardcodedCredentialSourceCallConfiguration conf
|
||||||
|
|||||||
@@ -11,11 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java
|
import java
|
||||||
import HardcodedCredentials
|
import semmle.code.java.security.HardcodedPasswordField
|
||||||
|
|
||||||
from PasswordVariable f, CompileTimeConstantExpr e
|
from PasswordVariable f, CompileTimeConstantExpr e
|
||||||
where
|
where passwordFieldAssignedHardcodedValue(f, e)
|
||||||
f instanceof Field and
|
|
||||||
f.getAnAssignedValue() = e and
|
|
||||||
not e.(StringLiteral).getValue() = ""
|
|
||||||
select f, "Sensitive field is assigned a hard-coded $@.", e, "value"
|
select f, "Sensitive field is assigned a hard-coded $@.", e, "value"
|
||||||
|
|||||||
Reference in New Issue
Block a user