Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions unified/ql/lib/codeql/unified/security/SensitiveData.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Provides classes and predicates for identifying sensitive data.
*
* 'Sensitive' data is anything that should not be sent in unencrypted form. This library tries to
* guess where sensitive data may either be stored in a variable or produced by a method.
*/

import unified
import codeql.concepts.internal.SensitiveDataHeuristics
private import codeql.unified.internal.typeinference.TypeInference as TypeInference

/**
* A data flow node that might contain sensitive data.
*/
cached
abstract class SensitiveData extends DataFlow::Node {
/**
* Gets the classification of sensitive data this expression might contain.
*/
cached
abstract SensitiveDataClassification getClassification();
}

/**
* An identifier that might contain sensitive data.
*/
private class SensitiveDataIdentifier extends SensitiveData {
SensitiveDataClassification classification;

SensitiveDataIdentifier() {
exists(IdentifierExpr e | e = this.asExpr() |
HeuristicNames::nameIndicatesSensitiveData(e.getValue(), classification)
)
}

override SensitiveDataClassification getClassification() { result = classification }
}

private Expr memberAccessParent(MemberAccessExpr e) { result = e.getParent() }

/**
* A member access that might contain sensitive data. This includes a member itself and
* components of a receiver chain, for example:
* ```
* object.password
* password.value
* password.getValue()
* ```
*/
private class SensitiveDataMemberAccess extends SensitiveData {
SensitiveDataClassification classification;

SensitiveDataMemberAccess() {
exists(MemberAccessExpr e | memberAccessParent*(e) = this.asExpr() |
HeuristicNames::nameIndicatesSensitiveData(e.getMemberName(), classification)
)
}

override SensitiveDataClassification getClassification() { result = classification }
}

/**
* A function call that might produce sensitive data.
*/
private class SensitiveDataCall extends SensitiveData {
SensitiveDataClassification classification;

SensitiveDataCall() {
exists(CallExpr call, string name |
call = this.asExpr() and
name = TypeInference::resolveCallTarget(call).(Member).getNameNode().getValue() and
HeuristicNames::nameIndicatesSensitiveData(name, classification)
)
}

override SensitiveDataClassification getClassification() { result = classification }
}
25 changes: 12 additions & 13 deletions unified/ql/src/queries/security/CWE-312/CleartextLogging.ql
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@
// FIXME: This is a deliberately dumb and noisy version of the query used to exercise data flow early on.
//
import unified
import codeql.concepts.internal.SensitiveDataHeuristics
import codeql.unified.security.SensitiveData

private string getNameFromExpr(Expr e) {
result = e.(IdentifierExpr).getValue()
or
result = e.(MemberAccessExpr).getMemberName()
}

module DummyConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) {
exists(string name |
name = getNameFromExpr(node.asExpr()) and
HeuristicNames::nameIndicatesSensitiveData(name)
)
}
/**
* A taint-tracking configuration for cleartext logging vulnerabilities.
*/
module CleartextLoggingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof SensitiveData }

predicate isSink(DataFlow::Node node) {
exists(CallExpr call |
Expand All @@ -43,10 +41,11 @@ module DummyConfig implements DataFlow::ConfigSig {
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}

module DummyFlow = TaintTracking::Global<DummyConfig>;
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;

import DummyFlow::PathGraph
import CleartextLoggingFlow::PathGraph

from DummyFlow::PathNode source, DummyFlow::PathNode sink
where DummyFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Logging of $@", source.getNode(), "sensitive data"
from CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink
where CleartextLoggingFlow::flowPath(source, sink)
select source.getNode(), source, sink, "This sensitive information is to $@ to a log file.", sink,
"written"
Loading
Loading