Merge pull request #3273 from Semmle/rdmarsh/cpp/RemoteFlowSource-model

C++: Add remote flow sources via models
This commit is contained in:
Jonas Jensen
2020-04-23 09:54:40 +02:00
committed by GitHub
4 changed files with 79 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.FlowSource
class Fread extends AliasFunction {
class Fread extends AliasFunction, RemoteFlowFunction {
Fread() { this.hasGlobalName("fread") }
override predicate parameterNeverEscapes(int n) {
@@ -11,4 +12,9 @@ class Fread extends AliasFunction {
override predicate parameterEscapesOnlyViaReturn(int n) { none() }
override predicate parameterIsAlwaysReturned(int n) { none() }
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
}
}

View File

@@ -3,12 +3,13 @@ import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.FlowSource
/**
* The standard functions `gets` and `fgets`.
*/
class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
SideEffectFunction {
SideEffectFunction, RemoteFlowFunction {
GetsFunction() {
exists(string name | hasGlobalOrStdName(name) |
name = "gets" or // gets(str)
@@ -42,4 +43,9 @@ class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, Alias
buffer = true and
mustWrite = true
}
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
output.isParameterDeref(0) and
description = "String read by " + this.getName()
}
}

View File

@@ -0,0 +1,21 @@
/**
* Provides a class for modeling functions that return data from potentially untrusted sources. To use
* this QL library, create a QL class extending `DataFlowFunction` with a
* characteristic predicate that selects the function or set of functions you
* are modeling. Within that class, override the predicates provided by
* `RemoteFlowFunction` to match the flow within that function.
*/
import cpp
import FunctionInputsAndOutputs
import semmle.code.cpp.models.Models
/**
* A library function which returns data read from a network connection.
*/
abstract class RemoteFlowFunction extends Function {
/**
* Holds if remote data described by `description` flows from `output` of a call to this function.
*/
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
}

View File

@@ -0,0 +1,44 @@
/**
* Provides classes representing various flow sources for taint tracking.
*/
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
import semmle.code.cpp.models.interfaces.FlowSource
/** A data flow source of remote user input. */
abstract class RemoteFlowSource extends DataFlow::Node {
/** Gets a string that describes the type of this remote flow source. */
abstract string getSourceType();
}
private class TaintedReturnSource extends RemoteFlowSource {
string sourceType;
TaintedReturnSource() {
exists(RemoteFlowFunction func, CallInstruction instr, FunctionOutput output |
asInstruction() = instr and
instr.getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and
output.isReturnValue()
)
}
override string getSourceType() { result = sourceType }
}
private class TaintedParameterSource extends RemoteFlowSource {
string sourceType;
TaintedParameterSource() {
exists(RemoteFlowFunction func, WriteSideEffectInstruction instr, FunctionOutput output |
asInstruction() = instr and
instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and
func.hasRemoteFlowSource(output, sourceType) and
output.isParameterDeref(instr.getIndex())
)
}
override string getSourceType() { result = sourceType }
}