mirror of
https://github.com/github/codeql.git
synced 2025-12-23 20:26:32 +01:00
Merge pull request #12435 from jketema/more-config
C++: Convert a number of data flow based queries to use `ConfigSig`
This commit is contained in:
@@ -17,7 +17,7 @@ import cpp
|
|||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.controlflow.IRGuards
|
import semmle.code.cpp.controlflow.IRGuards
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import DataFlow::PathGraph
|
import OverflowDestination::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `fc` is a call to a copy operation where the size argument contains
|
* Holds if `fc` is a call to a copy operation where the size argument contains
|
||||||
@@ -66,14 +66,12 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va
|
|||||||
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverflowDestinationConfig extends TaintTracking::Configuration {
|
module OverflowDestinationConfig implements DataFlow::ConfigSig {
|
||||||
OverflowDestinationConfig() { this = "OverflowDestinationConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asIndirectConvertedExpr()) }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asIndirectConvertedExpr()) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
exists(Variable checkedVar |
|
exists(Variable checkedVar |
|
||||||
readsVariable(node.asInstruction(), checkedVar) and
|
readsVariable(node.asInstruction(), checkedVar) and
|
||||||
hasUpperBoundsCheck(checkedVar)
|
hasUpperBoundsCheck(checkedVar)
|
||||||
@@ -86,11 +84,11 @@ class OverflowDestinationConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module OverflowDestination = TaintTracking::Make<OverflowDestinationConfig>;
|
||||||
FunctionCall fc, OverflowDestinationConfig conf, DataFlow::PathNode source,
|
|
||||||
DataFlow::PathNode sink
|
from FunctionCall fc, OverflowDestination::PathNode source, OverflowDestination::PathNode sink
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(source, sink) and
|
OverflowDestination::hasFlowPath(source, sink) and
|
||||||
sourceSized(fc, sink.getNode().asIndirectConvertedExpr())
|
sourceSized(fc, sink.getNode().asIndirectConvertedExpr())
|
||||||
select fc, source, sink,
|
select fc, source, sink,
|
||||||
"To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size."
|
"To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size."
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import NtohlArrayNoBound
|
import NtohlArrayNoBound
|
||||||
|
|
||||||
from NetworkToBufferSizeConfiguration bufConfig, DataFlow::Node source, DataFlow::Node sink
|
from DataFlow::Node source, DataFlow::Node sink
|
||||||
where bufConfig.hasFlow(source, sink)
|
where NetworkToBufferSizeFlow::hasFlow(source, sink)
|
||||||
select sink, "Unchecked use of data from network function $@.", source, source.toString()
|
select sink, "Unchecked use of data from network function $@.", source, source.toString()
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ class NetworkFunctionCall extends FunctionCall {
|
|||||||
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
|
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
|
deprecated class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
|
||||||
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
|
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
|
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
|
||||||
@@ -146,3 +146,19 @@ class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private module NetworkToBufferSizeConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node node) { node.asExpr() = any(BufferAccess ba).getAccessedLength() }
|
||||||
|
|
||||||
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
exists(GuardCondition gc, GVN gvn |
|
||||||
|
gc.getAChild*() = gvn.getAnExpr() and
|
||||||
|
globalValueNumber(node.asExpr()) = gvn and
|
||||||
|
gc.controls(node.asExpr().getBasicBlock(), _)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module NetworkToBufferSizeFlow = DataFlow::Make<NetworkToBufferSizeConfiguration>;
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ import ExternalAPIsSpecific
|
|||||||
|
|
||||||
/** A node representing untrusted data being passed to an external API. */
|
/** A node representing untrusted data being passed to an external API. */
|
||||||
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||||
UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) }
|
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) }
|
||||||
|
|
||||||
/** Gets a source of untrusted data which is passed to this external API data node. */
|
/** Gets a source of untrusted data which is passed to this external API data node. */
|
||||||
DataFlow::Node getAnUntrustedSource() {
|
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) }
|
||||||
any(UntrustedDataToExternalApiConfig c).hasFlow(result, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class ExternalApiDataNode extends DataFlow::Node {
|
|||||||
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
|
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
|
||||||
|
|
||||||
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
||||||
class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
||||||
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
|
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
override predicate isSource(DataFlow::Node source) {
|
||||||
@@ -60,3 +60,17 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
|
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
|
||||||
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
|
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
|
||||||
|
|
||||||
|
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
||||||
|
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
exists(RemoteFlowSourceFunction remoteFlow |
|
||||||
|
remoteFlow = source.asExpr().(Call).getTarget() and
|
||||||
|
remoteFlow.hasRemoteFlowSource(_, _)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
|
||||||
|
}
|
||||||
|
|
||||||
|
module UntrustedDataToExternalApiFlow = TaintTracking::Make<UntrustedDataToExternalApiConfig>;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import cpp
|
|||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import ir.ExternalAPIs
|
import ir.ExternalAPIs
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import DataFlow::PathGraph
|
import UntrustedDataToExternalApiFlow::PathGraph
|
||||||
|
|
||||||
from UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink
|
||||||
where config.hasFlowPath(source, sink)
|
where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink)
|
||||||
select sink, source, sink,
|
select sink, source, sink,
|
||||||
"Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() +
|
"Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() +
|
||||||
" with untrusted data from $@.", source, source.getNode().(RemoteFlowSource).getSourceType()
|
" with untrusted data from $@.", source, source.getNode().(RemoteFlowSource).getSourceType()
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import ExternalAPIs
|
import ExternalAPIs
|
||||||
import DataFlow::PathGraph
|
import UntrustedDataToExternalApiFlow::PathGraph
|
||||||
|
|
||||||
from UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink
|
||||||
where config.hasFlowPath(source, sink)
|
where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink)
|
||||||
select sink, source, sink,
|
select sink, source, sink,
|
||||||
"Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() +
|
"Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() +
|
||||||
" with untrusted data from $@.", source, source.toString()
|
" with untrusted data from $@.", source, source.toString()
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ import ExternalAPIsSpecific
|
|||||||
|
|
||||||
/** A node representing untrusted data being passed to an external API. */
|
/** A node representing untrusted data being passed to an external API. */
|
||||||
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||||
UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) }
|
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) }
|
||||||
|
|
||||||
/** Gets a source of untrusted data which is passed to this external API data node. */
|
/** Gets a source of untrusted data which is passed to this external API data node. */
|
||||||
DataFlow::Node getAnUntrustedSource() {
|
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) }
|
||||||
any(UntrustedDataToExternalApiConfig c).hasFlow(result, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class ExternalApiDataNode extends DataFlow::Node {
|
|||||||
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
|
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
|
||||||
|
|
||||||
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
||||||
class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
||||||
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
|
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
@@ -55,3 +55,12 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
|
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
|
||||||
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
|
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
|
||||||
|
|
||||||
|
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
|
||||||
|
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
|
||||||
|
}
|
||||||
|
|
||||||
|
module UntrustedDataToExternalApiFlow = TaintTracking::Make<UntrustedDataToExternalApiConfig>;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import semmle.code.cpp.controlflow.IRGuards
|
|||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||||
import DataFlow::PathGraph
|
import ImproperArrayIndexValidation::PathGraph
|
||||||
import semmle.code.cpp.security.Security
|
import semmle.code.cpp.security.Security
|
||||||
|
|
||||||
predicate hasUpperBound(VariableAccess offsetExpr) {
|
predicate hasUpperBound(VariableAccess offsetExpr) {
|
||||||
@@ -65,12 +65,10 @@ predicate predictableInstruction(Instruction instr) {
|
|||||||
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
predictableInstruction(instr.(UnaryInstruction).getUnary())
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
|
module ImproperArrayIndexValidationConfig implements DataFlow::ConfigSig {
|
||||||
ImproperArrayIndexValidationConfig() { this = "ImproperArrayIndexValidationConfig" }
|
predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
hasUpperBound(node.asExpr())
|
hasUpperBound(node.asExpr())
|
||||||
or
|
or
|
||||||
// These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
|
// These barriers are ported from `DefaultTaintTracking` because this query is quite noisy
|
||||||
@@ -107,7 +105,7 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
exists(ArrayExpr arrayExpr, VariableAccess offsetExpr |
|
exists(ArrayExpr arrayExpr, VariableAccess offsetExpr |
|
||||||
offsetExpr = arrayExpr.getArrayOffset() and
|
offsetExpr = arrayExpr.getArrayOffset() and
|
||||||
sink.asExpr() = offsetExpr and
|
sink.asExpr() = offsetExpr and
|
||||||
@@ -116,11 +114,13 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ImproperArrayIndexValidation = TaintTracking::Make<ImproperArrayIndexValidationConfig>;
|
||||||
|
|
||||||
from
|
from
|
||||||
ImproperArrayIndexValidationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink,
|
ImproperArrayIndexValidation::PathNode source, ImproperArrayIndexValidation::PathNode sink,
|
||||||
string sourceType
|
string sourceType
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(source, sink) and
|
ImproperArrayIndexValidation::hasFlowPath(source, sink) and
|
||||||
isFlowSource(source.getNode(), sourceType)
|
isFlowSource(source.getNode(), sourceType)
|
||||||
select sink.getNode(), source, sink,
|
select sink.getNode(), source, sink,
|
||||||
"An array indexing expression depends on $@ that might be outside the bounds of the array.",
|
"An array indexing expression depends on $@ that might be outside the bounds of the array.",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import semmle.code.cpp.security.Overflow
|
|||||||
import semmle.code.cpp.security.Security
|
import semmle.code.cpp.security.Security
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import DataFlow::PathGraph
|
import UncontrolledArith::PathGraph
|
||||||
import Bounded
|
import Bounded
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,10 +90,8 @@ predicate missingGuard(VariableAccess va, string effect) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UncontrolledArithConfiguration extends TaintTracking::Configuration {
|
module UncontrolledArithConfiguration implements DataFlow::ConfigSig {
|
||||||
UncontrolledArithConfiguration() { this = "UncontrolledArithConfiguration" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
||||||
rand.getFunctionOutput().isReturnValue() and
|
rand.getFunctionOutput().isReturnValue() and
|
||||||
source.asExpr() = call
|
source.asExpr() = call
|
||||||
@@ -105,9 +103,9 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) }
|
predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
bounded(node.asExpr())
|
bounded(node.asExpr())
|
||||||
or
|
or
|
||||||
// If this expression is part of bitwise 'and' or 'or' operation it's likely that the value is
|
// If this expression is part of bitwise 'and' or 'or' operation it's likely that the value is
|
||||||
@@ -124,14 +122,16 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module UncontrolledArith = TaintTracking::Make<UncontrolledArithConfiguration>;
|
||||||
|
|
||||||
/** Gets the expression that corresponds to `node`, if any. */
|
/** Gets the expression that corresponds to `node`, if any. */
|
||||||
Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] }
|
Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] }
|
||||||
|
|
||||||
from
|
from
|
||||||
UncontrolledArithConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
|
UncontrolledArith::PathNode source, UncontrolledArith::PathNode sink, VariableAccess va,
|
||||||
VariableAccess va, string effect
|
string effect
|
||||||
where
|
where
|
||||||
config.hasFlowPath(source, sink) and
|
UncontrolledArith::hasFlowPath(source, sink) and
|
||||||
sink.getNode().asExpr() = va and
|
sink.getNode().asExpr() = va and
|
||||||
missingGuard(va, effect)
|
missingGuard(va, effect)
|
||||||
select sink.getNode(), source, sink,
|
select sink.getNode(), source, sink,
|
||||||
|
|||||||
@@ -25,24 +25,22 @@ class SslGetVerifyResultCall extends FunctionCall {
|
|||||||
* Data flow from a call to `SSL_get_verify_result` to a guard condition
|
* Data flow from a call to `SSL_get_verify_result` to a guard condition
|
||||||
* that references the result.
|
* that references the result.
|
||||||
*/
|
*/
|
||||||
class VerifyResultConfig extends DataFlow::Configuration {
|
module VerifyResultConfig implements DataFlow::ConfigSig {
|
||||||
VerifyResultConfig() { this = "VerifyResultConfig" }
|
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SslGetVerifyResultCall }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
source.asExpr() instanceof SslGetVerifyResultCall
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(GuardCondition guard | guard.getAChild*() = sink.asExpr())
|
exists(GuardCondition guard | guard.getAChild*() = sink.asExpr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module VerifyResult = DataFlow::Make<VerifyResultConfig>;
|
||||||
|
|
||||||
from
|
from
|
||||||
VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2,
|
DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2, GuardCondition guard, Expr c1,
|
||||||
GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue
|
Expr c2, boolean testIsTrue
|
||||||
where
|
where
|
||||||
config.hasFlow(source, sink1) and
|
VerifyResult::hasFlow(source, sink1) and
|
||||||
config.hasFlow(source, sink2) and
|
VerifyResult::hasFlow(source, sink2) and
|
||||||
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
|
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
|
||||||
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
|
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
|
||||||
c1.getValue().toInt() = 0 and
|
c1.getValue().toInt() = 0 and
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import semmle.code.cpp.security.BufferWrite as BufferWrite
|
|||||||
import semmle.code.cpp.security.SensitiveExprs
|
import semmle.code.cpp.security.SensitiveExprs
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import DataFlow::PathGraph
|
import ToBufferFlow::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A buffer write into a sensitive expression.
|
* A buffer write into a sensitive expression.
|
||||||
@@ -39,27 +39,27 @@ class SensitiveBufferWrite extends Expr instanceof BufferWrite::BufferWrite {
|
|||||||
* A taint flow configuration for flow from user input to a buffer write
|
* A taint flow configuration for flow from user input to a buffer write
|
||||||
* into a sensitive expression.
|
* into a sensitive expression.
|
||||||
*/
|
*/
|
||||||
class ToBufferConfiguration extends TaintTracking::Configuration {
|
module ToBufferConfiguration implements DataFlow::ConfigSig {
|
||||||
ToBufferConfiguration() { this = "ToBufferConfiguration" }
|
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ToBufferFlow = TaintTracking::Make<ToBufferConfiguration>;
|
||||||
|
|
||||||
predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) {
|
predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) {
|
||||||
w.getASource() = sink.asIndirectExpr()
|
w.getASource() = sink.asIndirectExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
from
|
||||||
ToBufferConfiguration config, SensitiveBufferWrite w, DataFlow::PathNode sourceNode,
|
SensitiveBufferWrite w, ToBufferFlow::PathNode sourceNode, ToBufferFlow::PathNode sinkNode,
|
||||||
DataFlow::PathNode sinkNode, FlowSource source
|
FlowSource source
|
||||||
where
|
where
|
||||||
config.hasFlowPath(sourceNode, sinkNode) and
|
ToBufferFlow::hasFlowPath(sourceNode, sinkNode) and
|
||||||
sourceNode.getNode() = source and
|
sourceNode.getNode() = source and
|
||||||
isSinkImpl(sinkNode.getNode(), w)
|
isSinkImpl(sinkNode.getNode(), w)
|
||||||
select w, sourceNode, sinkNode,
|
select w, sourceNode, sinkNode,
|
||||||
|
|||||||
@@ -18,23 +18,23 @@ import semmle.code.cpp.security.FileWrite
|
|||||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import DataFlow::PathGraph
|
import FromSensitiveFlow::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink.
|
* A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink.
|
||||||
*/
|
*/
|
||||||
class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||||
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
|
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||||
|
|
||||||
predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) {
|
predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) {
|
||||||
exists(Expr e |
|
exists(Expr e |
|
||||||
e = [sink.asExpr(), sink.asIndirectExpr()] and
|
e = [sink.asExpr(), sink.asIndirectExpr()] and
|
||||||
@@ -78,10 +78,10 @@ predicate isFileName(GVN gvn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
from
|
from
|
||||||
FromSensitiveConfiguration config, SensitiveExpr source, DataFlow::PathNode sourceNode,
|
SensitiveExpr source, FromSensitiveFlow::PathNode sourceNode, FromSensitiveFlow::PathNode midNode,
|
||||||
DataFlow::PathNode midNode, FileWrite w, Expr dest
|
FileWrite w, Expr dest
|
||||||
where
|
where
|
||||||
config.hasFlowPath(sourceNode, midNode) and
|
FromSensitiveFlow::hasFlowPath(sourceNode, midNode) and
|
||||||
isSourceImpl(sourceNode.getNode(), source) and
|
isSourceImpl(sourceNode.getNode(), source) and
|
||||||
isSinkImpl(midNode.getNode(), w, dest)
|
isSinkImpl(midNode.getNode(), w, dest)
|
||||||
select w, sourceNode, midNode,
|
select w, sourceNode, midNode,
|
||||||
|
|||||||
@@ -16,11 +16,9 @@ import cpp
|
|||||||
import semmle.code.cpp.security.SensitiveExprs
|
import semmle.code.cpp.security.SensitiveExprs
|
||||||
import semmle.code.cpp.security.PrivateData
|
import semmle.code.cpp.security.PrivateData
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking2
|
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking3
|
|
||||||
import semmle.code.cpp.models.interfaces.FlowSource
|
import semmle.code.cpp.models.interfaces.FlowSource
|
||||||
import semmle.code.cpp.commons.File
|
import semmle.code.cpp.commons.File
|
||||||
import DataFlow::PathGraph
|
import FromSensitiveFlow::PathGraph
|
||||||
|
|
||||||
class SourceVariable extends Variable {
|
class SourceVariable extends Variable {
|
||||||
SourceVariable() {
|
SourceVariable() {
|
||||||
@@ -236,72 +234,70 @@ predicate isSourceImpl(DataFlow::Node source) {
|
|||||||
* A taint flow configuration for flow from a sensitive expression to a network
|
* A taint flow configuration for flow from a sensitive expression to a network
|
||||||
* operation.
|
* operation.
|
||||||
*/
|
*/
|
||||||
class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||||
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
|
predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isSourceImpl(source) }
|
predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizerIn(DataFlow::Node node) {
|
predicate isBarrierIn(DataFlow::Node node) {
|
||||||
// As any use of a sensitive variable is a potential source, we need to block flow into
|
// As any use of a sensitive variable is a potential source, we need to block flow into
|
||||||
// sources to not get path duplication.
|
// sources to not get path duplication.
|
||||||
this.isSource(node)
|
isSource(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A taint flow configuration for flow from a sensitive expression to an encryption operation.
|
* A taint flow configuration for flow from a sensitive expression to an encryption operation.
|
||||||
*/
|
*/
|
||||||
class ToEncryptionConfiguration extends TaintTracking2::Configuration {
|
module ToEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||||
ToEncryptionConfiguration() { this = "ToEncryptionConfiguration" }
|
predicate isSource(DataFlow::Node source) { FromSensitiveFlow::hasFlow(source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
|
||||||
any(FromSensitiveConfiguration config).hasFlow(source, _)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizerIn(DataFlow::Node node) {
|
predicate isBarrierIn(DataFlow::Node node) {
|
||||||
// As any use of a sensitive variable is a potential source, we need to block flow into
|
// As any use of a sensitive variable is a potential source, we need to block flow into
|
||||||
// sources to not get path duplication.
|
// sources to not get path duplication.
|
||||||
this.isSource(node)
|
isSource(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ToEncryptionFlow = TaintTracking::Make<ToEncryptionConfiguration>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A taint flow configuration for flow from an encryption operation to a network operation.
|
* A taint flow configuration for flow from an encryption operation to a network operation.
|
||||||
*/
|
*/
|
||||||
class FromEncryptionConfiguration extends TaintTracking3::Configuration {
|
module FromEncryptionConfiguration implements DataFlow::ConfigSig {
|
||||||
FromEncryptionConfiguration() { this = "FromEncryptionConfiguration" }
|
predicate isSource(DataFlow::Node source) { isSinkEncrypt(source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isSinkEncrypt(source, _) }
|
predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::hasFlowTo(sink) }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
any(FromSensitiveConfiguration config).hasFlowTo(sink)
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, NetworkSendRecv networkSendRecv, string msg
|
module FromEncryptionFlow = TaintTracking::Make<FromEncryptionConfiguration>;
|
||||||
|
|
||||||
|
from
|
||||||
|
FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
||||||
|
NetworkSendRecv networkSendRecv, string msg
|
||||||
where
|
where
|
||||||
// flow from sensitive -> network data
|
// flow from sensitive -> network data
|
||||||
any(FromSensitiveConfiguration config).hasFlowPath(source, sink) and
|
FromSensitiveFlow::hasFlowPath(source, sink) and
|
||||||
isSinkSendRecv(sink.getNode(), networkSendRecv) and
|
isSinkSendRecv(sink.getNode(), networkSendRecv) and
|
||||||
// no flow from sensitive -> evidence of encryption
|
// no flow from sensitive -> evidence of encryption
|
||||||
not any(ToEncryptionConfiguration config).hasFlow(source.getNode(), _) and
|
not ToEncryptionFlow::hasFlow(source.getNode(), _) and
|
||||||
not any(FromEncryptionConfiguration config).hasFlowTo(sink.getNode()) and
|
not FromEncryptionFlow::hasFlowTo(sink.getNode()) and
|
||||||
// construct result
|
// construct result
|
||||||
if networkSendRecv instanceof NetworkSend
|
if networkSendRecv instanceof NetworkSend
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.security.SensitiveExprs
|
import semmle.code.cpp.security.SensitiveExprs
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import DataFlow::PathGraph
|
import FromSensitiveFlow::PathGraph
|
||||||
|
|
||||||
class SqliteFunctionCall extends FunctionCall {
|
class SqliteFunctionCall extends FunctionCall {
|
||||||
SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") }
|
SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") }
|
||||||
@@ -56,21 +56,19 @@ predicate isSinkImpl(DataFlow::Node sink, SqliteFunctionCall c, Type t) {
|
|||||||
/**
|
/**
|
||||||
* A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
|
* A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
|
||||||
*/
|
*/
|
||||||
class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
module FromSensitiveConfiguration implements DataFlow::ConfigSig {
|
||||||
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
|
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
isSinkImpl(sink, _, _) and
|
isSinkImpl(sink, _, _) and
|
||||||
not sqlite_encryption_used()
|
not sqlite_encryption_used()
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) {
|
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) {
|
||||||
// flow out from fields at the sink (only).
|
// flow out from fields at the sink (only).
|
||||||
// constrain `content` to a field inside the node.
|
// constrain `content` to a field inside the node.
|
||||||
exists(Type t |
|
exists(Type t |
|
||||||
@@ -80,11 +78,13 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module FromSensitiveFlow = TaintTracking::Make<FromSensitiveConfiguration>;
|
||||||
|
|
||||||
from
|
from
|
||||||
FromSensitiveConfiguration config, SensitiveExpr sensitive, DataFlow::PathNode source,
|
SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink,
|
||||||
DataFlow::PathNode sink, SqliteFunctionCall sqliteCall
|
SqliteFunctionCall sqliteCall
|
||||||
where
|
where
|
||||||
config.hasFlowPath(source, sink) and
|
FromSensitiveFlow::hasFlowPath(source, sink) and
|
||||||
isSourceImpl(source.getNode(), sensitive) and
|
isSourceImpl(source.getNode(), sensitive) and
|
||||||
isSinkImpl(sink.getNode(), sqliteCall, _)
|
isSinkImpl(sink.getNode(), sqliteCall, _)
|
||||||
select sqliteCall, source, sink,
|
select sqliteCall, source, sink,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||||
import DataFlow::PathGraph
|
import HttpStringToUrlOpen::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string matching private host names of IPv4 and IPv6, which only matches
|
* A string matching private host names of IPv4 and IPv6, which only matches
|
||||||
@@ -54,10 +54,8 @@ class HttpStringLiteral extends StringLiteral {
|
|||||||
/**
|
/**
|
||||||
* Taint tracking configuration for HTTP connections.
|
* Taint tracking configuration for HTTP connections.
|
||||||
*/
|
*/
|
||||||
class HttpStringToUrlOpenConfig extends TaintTracking::Configuration {
|
module HttpStringToUrlOpenConfig implements DataFlow::ConfigSig {
|
||||||
HttpStringToUrlOpenConfig() { this = "HttpStringToUrlOpenConfig" }
|
predicate isSource(DataFlow::Node src) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) {
|
|
||||||
// Sources are strings containing an HTTP URL not in a private domain.
|
// Sources are strings containing an HTTP URL not in a private domain.
|
||||||
src.asIndirectExpr() instanceof HttpStringLiteral and
|
src.asIndirectExpr() instanceof HttpStringLiteral and
|
||||||
// block taint starting at `strstr`, which is likely testing an existing URL, rather than constructing an HTTP URL.
|
// block taint starting at `strstr`, which is likely testing an existing URL, rather than constructing an HTTP URL.
|
||||||
@@ -67,7 +65,7 @@ class HttpStringToUrlOpenConfig extends TaintTracking::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
// Sinks can be anything that demonstrates the string is likely to be
|
// Sinks can be anything that demonstrates the string is likely to be
|
||||||
// accessed as a URL, for example using it in a network access. Some
|
// accessed as a URL, for example using it in a network access. Some
|
||||||
// URLs are only ever displayed or used for data processing.
|
// URLs are only ever displayed or used for data processing.
|
||||||
@@ -91,10 +89,10 @@ class HttpStringToUrlOpenConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module HttpStringToUrlOpen = TaintTracking::Make<HttpStringToUrlOpenConfig>;
|
||||||
HttpStringToUrlOpenConfig config, DataFlow::PathNode source, DataFlow::PathNode sink,
|
|
||||||
HttpStringLiteral str
|
from HttpStringToUrlOpen::PathNode source, HttpStringToUrlOpen::PathNode sink, HttpStringLiteral str
|
||||||
where
|
where
|
||||||
config.hasFlowPath(source, sink) and
|
HttpStringToUrlOpen::hasFlowPath(source, sink) and
|
||||||
str = source.getNode().asIndirectExpr()
|
str = source.getNode().asIndirectExpr()
|
||||||
select str, source, sink, "This URL may be constructed with the HTTP protocol."
|
select str, source, sink, "This URL may be constructed with the HTTP protocol."
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
import semmle.code.cpp.ir.IR
|
import semmle.code.cpp.ir.IR
|
||||||
import DataFlow::PathGraph
|
import KeyStrengthFlow::PathGraph
|
||||||
|
|
||||||
// Gets the recommended minimum key size (in bits) of `func`, the name of an encryption function that accepts a key size as parameter `paramIndex`
|
// Gets the recommended minimum key size (in bits) of `func`, the name of an encryption function that accepts a key size as parameter `paramIndex`
|
||||||
int getMinimumKeyStrength(string func, int paramIndex) {
|
int getMinimumKeyStrength(string func, int paramIndex) {
|
||||||
@@ -28,10 +28,8 @@ int getMinimumKeyStrength(string func, int paramIndex) {
|
|||||||
result = 2048
|
result = 2048
|
||||||
}
|
}
|
||||||
|
|
||||||
class KeyStrengthFlow extends DataFlow::Configuration {
|
module KeyStrengthFlowConfiguration implements DataFlow::ConfigSig {
|
||||||
KeyStrengthFlow() { this = "KeyStrengthFlow" }
|
predicate isSource(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) {
|
|
||||||
exists(int bits |
|
exists(int bits |
|
||||||
node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and
|
node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and
|
||||||
bits < getMinimumKeyStrength(_, _) and
|
bits < getMinimumKeyStrength(_, _) and
|
||||||
@@ -39,7 +37,7 @@ class KeyStrengthFlow extends DataFlow::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
exists(FunctionCall fc, string name, int param |
|
exists(FunctionCall fc, string name, int param |
|
||||||
node.asExpr() = fc.getArgument(param) and
|
node.asExpr() = fc.getArgument(param) and
|
||||||
fc.getTarget().hasGlobalName(name) and
|
fc.getTarget().hasGlobalName(name) and
|
||||||
@@ -48,11 +46,13 @@ class KeyStrengthFlow extends DataFlow::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module KeyStrengthFlow = DataFlow::Make<KeyStrengthFlowConfiguration>;
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, KeyStrengthFlow conf, FunctionCall fc,
|
KeyStrengthFlow::PathNode source, KeyStrengthFlow::PathNode sink, FunctionCall fc, int param,
|
||||||
int param, string name, int minimumBits, int bits
|
string name, int minimumBits, int bits
|
||||||
where
|
where
|
||||||
conf.hasFlowPath(source, sink) and
|
KeyStrengthFlow::hasFlowPath(source, sink) and
|
||||||
sink.getNode().asExpr() = fc.getArgument(param) and
|
sink.getNode().asExpr() = fc.getArgument(param) and
|
||||||
fc.getTarget().hasGlobalName(name) and
|
fc.getTarget().hasGlobalName(name) and
|
||||||
minimumBits = getMinimumKeyStrength(name, param) and
|
minimumBits = getMinimumKeyStrength(name, param) and
|
||||||
|
|||||||
@@ -15,15 +15,13 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.models.interfaces.FlowSource
|
import semmle.code.cpp.models.interfaces.FlowSource
|
||||||
import DataFlow::PathGraph
|
import ExposedSystemData::PathGraph
|
||||||
import SystemData
|
import SystemData
|
||||||
|
|
||||||
class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
module ExposedSystemDataConfiguration implements DataFlow::ConfigSig {
|
||||||
ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" }
|
predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(FunctionCall fc, FunctionInput input, int arg |
|
exists(FunctionCall fc, FunctionInput input, int arg |
|
||||||
fc.getTarget().(RemoteFlowSinkFunction).hasRemoteFlowSink(input, _) and
|
fc.getTarget().(RemoteFlowSinkFunction).hasRemoteFlowSink(input, _) and
|
||||||
input.isParameterDeref(arg) and
|
input.isParameterDeref(arg) and
|
||||||
@@ -32,13 +30,15 @@ class ExposedSystemDataConfiguration extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from ExposedSystemDataConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
module ExposedSystemData = TaintTracking::Make<ExposedSystemDataConfiguration>;
|
||||||
|
|
||||||
|
from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink
|
||||||
where
|
where
|
||||||
config.hasFlowPath(source, sink) and
|
ExposedSystemData::hasFlowPath(source, sink) and
|
||||||
not exists(
|
not exists(
|
||||||
DataFlow::Node alt // remove duplicate results on conversions
|
DataFlow::Node alt // remove duplicate results on conversions
|
||||||
|
|
|
|
||||||
config.hasFlow(source.getNode(), alt) and
|
ExposedSystemData::hasFlow(source.getNode(), alt) and
|
||||||
alt.asConvertedExpr() = sink.getNode().asIndirectExpr() and
|
alt.asConvertedExpr() = sink.getNode().asIndirectExpr() and
|
||||||
alt != sink.getNode()
|
alt != sink.getNode()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: deprecated
|
||||||
|
---
|
||||||
|
* The `NetworkToBufferSizeConfiguration` and `UntrustedDataToExternalApiConfig` dataflow configurations have been deprecated. Please use `NetworkToBufferSizeFlow` and `UntrustedDataToExternalApiFlow`.
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||||
import semmle.code.cpp.security.FlowSources
|
import semmle.code.cpp.security.FlowSources
|
||||||
import DataFlow::PathGraph
|
import WordexpTaint::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `wordexp` function, which can perform command substitution.
|
* The `wordexp` function, which can perform command substitution.
|
||||||
@@ -35,24 +35,24 @@ private predicate isCommandSubstitutionDisabled(FunctionCall fc) {
|
|||||||
/**
|
/**
|
||||||
* A configuration to track user-supplied data to the `wordexp` function.
|
* A configuration to track user-supplied data to the `wordexp` function.
|
||||||
*/
|
*/
|
||||||
class WordexpTaintConfiguration extends TaintTracking::Configuration {
|
module WordexpTaintConfiguration implements DataFlow::ConfigSig {
|
||||||
WordexpTaintConfiguration() { this = "WordexpTaintConfiguration" }
|
predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
|
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
|
||||||
fc.getArgument(0) = sink.asExpr() and
|
fc.getArgument(0) = sink.asExpr() and
|
||||||
not isCommandSubstitutionDisabled(fc)
|
not isCommandSubstitutionDisabled(fc)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from WordexpTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode
|
module WordexpTaint = TaintTracking::Make<WordexpTaintConfiguration>;
|
||||||
where conf.hasFlowPath(sourceNode, sinkNode)
|
|
||||||
|
from WordexpTaint::PathNode sourceNode, WordexpTaint::PathNode sinkNode
|
||||||
|
where WordexpTaint::hasFlowPath(sourceNode, sinkNode)
|
||||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||||
"Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection."
|
"Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection."
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.models.interfaces.Allocation
|
import semmle.code.cpp.models.interfaces.Allocation
|
||||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||||
import DataFlow::PathGraph
|
import MultToAlloc::PathGraph
|
||||||
|
|
||||||
class MultToAllocConfig extends DataFlow::Configuration {
|
module MultToAllocConfig implements DataFlow::ConfigSig {
|
||||||
MultToAllocConfig() { this = "MultToAllocConfig" }
|
predicate isSource(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node node) {
|
|
||||||
// a multiplication of two non-constant expressions
|
// a multiplication of two non-constant expressions
|
||||||
exists(MulExpr me |
|
exists(MulExpr me |
|
||||||
me = node.asExpr() and
|
me = node.asExpr() and
|
||||||
@@ -28,14 +26,16 @@ class MultToAllocConfig extends DataFlow::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node node) {
|
predicate isSink(DataFlow::Node node) {
|
||||||
// something that affects an allocation size
|
// something that affects an allocation size
|
||||||
node.asExpr() = any(HeuristicAllocationExpr ae).getSizeExpr().getAChild*()
|
node.asExpr() = any(HeuristicAllocationExpr ae).getSizeExpr().getAChild*()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from MultToAllocConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
module MultToAlloc = DataFlow::Make<MultToAllocConfig>;
|
||||||
where config.hasFlowPath(source, sink)
|
|
||||||
|
from MultToAlloc::PathNode source, MultToAlloc::PathNode sink
|
||||||
|
where MultToAlloc::hasFlowPath(source, sink)
|
||||||
select sink, source, sink,
|
select sink, source, sink,
|
||||||
"Potentially overflowing value from $@ is used in the size of this allocation.", source,
|
"Potentially overflowing value from $@ is used in the size of this allocation.", source,
|
||||||
"multiplication"
|
"multiplication"
|
||||||
|
|||||||
Reference in New Issue
Block a user