Python: Extend command-injection to handle fabric.api.execute

This commit is contained in:
Rasmus Wriedt Larsen
2020-05-26 10:22:27 +02:00
parent e04d1ffcd2
commit 9c75a39b81
3 changed files with 53 additions and 0 deletions

View File

@@ -32,6 +32,8 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration {
override predicate isExtension(TaintTracking::Extension extension) {
extension instanceof FirstElementFlow
or
extension instanceof FabricExecuteExtension
}
}

View File

@@ -231,3 +231,41 @@ class FabricV1Commands extends CommandSink {
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* An extension that propagates taint from the arguments of `fabric.api.execute(func, arg0, arg1, ...)`
* to the parameters of `func`, since this will call `func(arg0, arg1, ...)`.
*/
class FabricExecuteExtension extends DataFlowExtension::DataFlowNode {
CallNode call;
FabricExecuteExtension() {
call = Value::named("fabric.api.execute").getACall() and
(
this = call.getArg(any(int i | i > 0))
or
this = call.getArgByName(any(string s | not s = "task"))
)
}
override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) {
tokind = fromkind and
exists(CallableValue func |
(
call.getArg(0).pointsTo(func)
or
call.getArgByName("task").pointsTo(func)
) and
exists(int i |
// execute(func, arg0, arg1) => func(arg0, arg1)
this = call.getArg(i) and
result = func.getParameter(i - 1)
)
or
exists(string name |
this = call.getArgByName(name) and
result = func.getParameterByName(name)
)
)
}
}

View File

@@ -1,6 +1,7 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.injection.Command
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
@@ -9,3 +10,15 @@ class SimpleSource extends TaintSource {
override string toString() { result = "taint source" }
}
class FabricExecuteTestConfiguration extends TaintTracking::Configuration {
FabricExecuteTestConfiguration() { this = "FabricExecuteTestConfiguration" }
override predicate isSource(TaintTracking::Source source) { source instanceof SimpleSource }
override predicate isSink(TaintTracking::Sink sink) { sink instanceof CommandSink }
override predicate isExtension(TaintTracking::Extension extension) {
extension instanceof FabricExecuteExtension
}
}