|
| 1 | +import semmle.code.cpp.dataflow.TaintTracking |
| 2 | +import semmle.code.cpp.models.interfaces.FlowSource |
| 3 | +import semmle.code.cpp.models.interfaces.DataFlow |
| 4 | +import SafeExternalAPIFunction |
| 5 | + |
| 6 | +/** A node representing untrusted data being passed to an external API. */ |
| 7 | +class ExternalAPIDataNode extends DataFlow::Node { |
| 8 | + Call call; |
| 9 | + int i; |
| 10 | + |
| 11 | + ExternalAPIDataNode() { |
| 12 | + // Argument to call to a function |
| 13 | + ( |
| 14 | + this.asExpr() = call.getArgument(i) |
| 15 | + or |
| 16 | + i = -1 and this.asExpr() = call.getQualifier() |
| 17 | + ) and |
| 18 | + exists(Function f | |
| 19 | + f = call.getTarget() and |
| 20 | + // Defined outside the source archive |
| 21 | + not f.hasDefinition() and |
| 22 | + // Not already modeled as a dataflow or taint step |
| 23 | + not f instanceof DataFlowFunction and |
| 24 | + not f instanceof TaintFunction and |
| 25 | + // Not a call to a known safe external API |
| 26 | + not f instanceof SafeExternalAPIFunction |
| 27 | + ) |
| 28 | + } |
| 29 | + |
| 30 | + /** Gets the called API `Function`. */ |
| 31 | + Function getExternalFunction() { result = call.getTarget() } |
| 32 | + |
| 33 | + /** Gets the index which is passed untrusted data (where -1 indicates the qualifier). */ |
| 34 | + int getIndex() { result = i } |
| 35 | + |
| 36 | + /** Gets the description of the function being called. */ |
| 37 | + string getFunctionDescription() { result = getExternalFunction().toString() } |
| 38 | +} |
| 39 | + |
| 40 | +/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */ |
| 41 | +class UntrustedDataToExternalAPIConfig extends TaintTracking::Configuration { |
| 42 | + UntrustedDataToExternalAPIConfig() { this = "UntrustedDataToExternalAPIConfig" } |
| 43 | + |
| 44 | + override predicate isSource(DataFlow::Node source) { |
| 45 | + exists(RemoteFlowFunction remoteFlow | |
| 46 | + remoteFlow = source.asExpr().(Call).getTarget() and |
| 47 | + remoteFlow.hasRemoteFlowSource(_, _) |
| 48 | + ) |
| 49 | + } |
| 50 | + |
| 51 | + override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalAPIDataNode } |
| 52 | +} |
0 commit comments