зеркало из https://github.com/github/codeql.git
Python taint-tracking. Add some tests and fix up various parts of the implementation.
This commit is contained in:
Родитель
eed2090168
Коммит
74f1dd3ec0
|
@ -5,10 +5,8 @@ private import semmle.python.objects.ObjectInternal
|
|||
newtype TTaintTrackingContext =
|
||||
TNoParam()
|
||||
or
|
||||
TParamContext(TaintKind param, int n) {
|
||||
exists(CallNode call |
|
||||
param.taints(call.getArg(n))
|
||||
)
|
||||
TParamContext(TaintKind param, AttributePath path, int n) {
|
||||
any(TaintTrackingImplementation impl).callWithTaintedArgument(_, _, _, _, n, path, param)
|
||||
}
|
||||
|
||||
class TaintTrackingContext extends TTaintTrackingContext {
|
||||
|
@ -16,21 +14,25 @@ class TaintTrackingContext extends TTaintTrackingContext {
|
|||
string toString() {
|
||||
this = TNoParam() and result = "No context"
|
||||
or
|
||||
exists(TaintKind param, int n |
|
||||
this = TParamContext(param, n) and
|
||||
result = "Parameter " + n.toString() + " is " + param
|
||||
exists(TaintKind param, AttributePath path, int n |
|
||||
this = TParamContext(param, path, n) and
|
||||
result = "Parameter " + n.toString() + "(" + path.toString() + ") is " + param
|
||||
)
|
||||
}
|
||||
|
||||
TaintKind getParameterTaint(int n) {
|
||||
this = TParamContext(result, n)
|
||||
this = TParamContext(result, _, n)
|
||||
}
|
||||
|
||||
AttributePath getAttributePath() {
|
||||
this = TParamContext(_, result, _)
|
||||
}
|
||||
|
||||
TaintTrackingContext getCaller() {
|
||||
exists(TaintKind param, int n |
|
||||
this = TParamContext(param, n) and
|
||||
exists(TaintKind param, AttributePath path, int n |
|
||||
this = TParamContext(param, path, n) and
|
||||
exists(TaintTrackingImplementation impl |
|
||||
impl.callWithTaintedArgument(_, _, result, _, n, TNoAttribute(), param)
|
||||
impl.callWithTaintedArgument(_, _, result, _, n, path, param)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -158,7 +160,7 @@ class TaintTrackingImplementation extends string {
|
|||
|
||||
predicate isPathSink(TaintTrackingNode sink) {
|
||||
exists(DataFlow::Node sinknode, TaintKind kind |
|
||||
sink = TTaintTrackingNode_(sinknode, TNoParam(), TNoAttribute(), kind, this) and
|
||||
sink = TTaintTrackingNode_(sinknode, _, TNoAttribute(), kind, this) and
|
||||
this.(TaintTracking::Configuration).isSink(sinknode, kind)
|
||||
)
|
||||
}
|
||||
|
@ -181,20 +183,26 @@ class TaintTrackingImplementation extends string {
|
|||
this.importStep(src, node, context, path, kind)
|
||||
or
|
||||
this.fromImportStep(src, node, context, path, kind)
|
||||
or
|
||||
this.attributeLoadStep(src, node, context, path, kind)
|
||||
or
|
||||
this.getattrStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.attributeLoadStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.getattrStep(src, node, context, path, kind)
|
||||
or
|
||||
this.useStep(src, node, context, path, kind)
|
||||
or
|
||||
this.callTaintStep(src, node, context, path, kind)
|
||||
or
|
||||
this.callFlowStep(src, node, context, path, kind)
|
||||
this.returnFlowStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.iterationStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.yieldStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.subscriptStep(src, node, context, path, kind)
|
||||
//or
|
||||
//this.ifExprStep(src, node, context, path, kind)
|
||||
or
|
||||
this.iterationStep(src, node, context, path, kind)
|
||||
or
|
||||
this.yieldStep(src, node, context, path, kind)
|
||||
this.essaFlowStep(src, node, context, path, kind)
|
||||
or
|
||||
exists(DataFlow::Node srcnode, TaintKind srckind |
|
||||
this.(TaintTracking::Configuration).isAdditionalFlowStep(srcnode, node, srckind, kind) and
|
||||
|
@ -259,35 +267,40 @@ class TaintTrackingImplementation extends string {
|
|||
)
|
||||
}
|
||||
|
||||
//pragma [noinline]
|
||||
//predicate argumentFlowStep(TaintTrackingNode src, DataFlow::Node node, TaintTrackingContext context, AttributePath path, TaintKind kind) {
|
||||
// exists(CallNode call, PythonFunctionObjectInternal pyfunc, int arg |
|
||||
// this.callWithTaintedArgument(src, call, _, pyfunc, arg, path, kind) and
|
||||
// node.asCfgNode() = pyfunc.getParameter(arg) and
|
||||
// context = TParamContext(kind, arg)
|
||||
// )
|
||||
// // TO DO... named parameters
|
||||
//}
|
||||
|
||||
pragma [noinline]
|
||||
predicate callFlowStep(TaintTrackingNode src, DataFlow::Node node, TaintTrackingContext context, AttributePath path, TaintKind kind) {
|
||||
exists(CallNode call, PythonFunctionObjectInternal pyfunc, int arg |
|
||||
this.callWithTaintedArgument(src, call, _, pyfunc, arg, path, kind) and
|
||||
node.asCfgNode() = pyfunc.getParameter(arg) and
|
||||
context = TParamContext(kind, arg)
|
||||
predicate returnFlowStep(TaintTrackingNode src, DataFlow::Node node, TaintTrackingContext context, AttributePath path, TaintKind kind) {
|
||||
exists(CallNode call, PythonFunctionObjectInternal pyfunc, int arg, TaintKind callerKind, DataFlow::Node srcNode, AttributePath callerPath, TaintTrackingContext srcContext |
|
||||
src = TTaintTrackingNode_(srcNode, srcContext, path, kind, this) and
|
||||
this.callWithTaintedArgument(_, call, context, pyfunc, arg, callerPath, callerKind) and
|
||||
srcContext = TParamContext(callerKind, callerPath, arg) and
|
||||
node.asCfgNode() = call and
|
||||
srcNode.asCfgNode() = any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode()
|
||||
)
|
||||
or
|
||||
exists(CallNode call, PythonFunctionObjectInternal pyfunc, int arg |
|
||||
this.callWithTaintedArgument(src, call, context, pyfunc, arg, path, kind) and
|
||||
src.getContext() = TParamContext(kind, arg)
|
||||
)
|
||||
// TO DO... named parameters
|
||||
}
|
||||
|
||||
predicate callWithTaintedArgument(TaintTrackingNode src, CallNode call, TaintTrackingContext caller, PythonFunctionObjectInternal pyfunc, int arg, AttributePath path, TaintKind kind) {
|
||||
predicate callWithTaintedArgument(TaintTrackingNode src, CallNode call, TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind) {
|
||||
exists(DataFlow::Node srcnode |
|
||||
src = TTaintTrackingNode_(srcnode, caller, path, kind, this) and
|
||||
srcnode.asCfgNode() = call.getArg(arg) and
|
||||
pyfunc.getACall() = call
|
||||
srcnode.asCfgNode() = pyfunc.getArgumentForCall(call, arg)
|
||||
)
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
predicate callTaintStep(TaintTrackingNode src, DataFlow::Node node, TaintTrackingContext context, AttributePath path, TaintKind kind) {
|
||||
exists(DataFlow::Node srcnode, CallNode call, string name |
|
||||
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
|
||||
exists(DataFlow::Node srcnode, CallNode call, TaintKind srckind, string name |
|
||||
src = TTaintTrackingNode_(srcnode, context, path, srckind, this) and
|
||||
call.getFunction().(AttrNode).getObject(name) = src.getNode().asCfgNode() and
|
||||
kind = src.getTaintKind().getTaintOfMethodResult(name) and
|
||||
kind = srckind.getTaintOfMethodResult(name) and
|
||||
node.asCfgNode() = call
|
||||
)
|
||||
}
|
||||
|
@ -366,7 +379,8 @@ class TaintTrackingImplementation extends string {
|
|||
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
|
||||
predvar = defn.getInput(pred) and
|
||||
not pred.unlikelySuccessor(defn.getBasicBlock()) and
|
||||
not predvar.(DataFlowExtension::DataFlowVariable).prunedSuccessor(defn.getVariable())
|
||||
not predvar.(DataFlowExtension::DataFlowVariable).prunedSuccessor(defn.getVariable()) and
|
||||
srcnode.asVariable() = predvar
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -390,11 +404,11 @@ class TaintTrackingImplementation extends string {
|
|||
|
||||
pragma [noinline]
|
||||
predicate taintedParameterDefinition(TaintTrackingNode src, ParameterDefinition defn, TaintTrackingContext context, AttributePath path, TaintKind kind) {
|
||||
exists(DataFlow::Node srcnode |
|
||||
src = TTaintTrackingNode_(srcnode, context, path, kind, this) and
|
||||
defn.getDefiningNode() = srcnode.asCfgNode()
|
||||
exists(CallNode call, PythonFunctionObjectInternal pyfunc, int arg |
|
||||
this.callWithTaintedArgument(src, call, _, pyfunc, arg, path, kind) and
|
||||
defn.getDefiningNode() = pyfunc.getParameter(arg) and
|
||||
context = TParamContext(kind, path, arg)
|
||||
)
|
||||
// TO DO... class intializers
|
||||
}
|
||||
|
||||
pragma [noinline]
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
edges
|
||||
| carrier.py:21:5:21:5 | explicit.carrier at carrier.py:21 | carrier.py:22:10:22:10 | explicit.carrier at carrier.py:22 |
|
||||
| carrier.py:21:9:21:28 | explicit.carrier at carrier.py:21 | carrier.py:21:5:21:5 | explicit.carrier at carrier.py:21 |
|
||||
| carrier.py:22:10:22:10 | explicit.carrier at carrier.py:22 | carrier.py:22:10:22:22 | simple.test at carrier.py:22 |
|
||||
| rockpaperscissors.py:24:5:24:5 | rock at rockpaperscissors.py:24 | rockpaperscissors.py:25:9:25:9 | rock at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:24:9:24:12 | rock at rockpaperscissors.py:24 | rockpaperscissors.py:24:5:24:5 | rock at rockpaperscissors.py:24 |
|
||||
| rockpaperscissors.py:25:5:25:5 | paper at rockpaperscissors.py:25 | rockpaperscissors.py:26:14:26:14 | paper at rockpaperscissors.py:26 |
|
||||
| rockpaperscissors.py:25:9:25:9 | rock at rockpaperscissors.py:25 | rockpaperscissors.py:25:9:25:16 | scissors at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:25:9:25:16 | scissors at rockpaperscissors.py:25 | rockpaperscissors.py:25:9:25:23 | paper at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:25:9:25:23 | paper at rockpaperscissors.py:25 | rockpaperscissors.py:25:5:25:5 | paper at rockpaperscissors.py:25 |
|
||||
| test.py:6:5:6:5 | simple.test at test.py:6 | test.py:7:10:7:10 | simple.test at test.py:7 |
|
||||
| test.py:6:9:6:14 | simple.test at test.py:6 | test.py:6:5:6:5 | simple.test at test.py:6 |
|
||||
| test.py:12:10:12:12 | simple.test at test.py:12 | test.py:13:10:13:12 | simple.test at test.py:13 |
|
||||
| test.py:20:5:20:5 | simple.test at test.py:20 | test.py:21:10:21:10 | simple.test at test.py:21 |
|
||||
| test.py:20:9:20:14 | simple.test at test.py:20 | test.py:20:5:20:5 | simple.test at test.py:20 |
|
||||
| test.py:21:10:21:10 | simple.test at test.py:21 | test.py:12:10:12:12 | simple.test at test.py:12 |
|
||||
| test.py:37:9:37:9 | simple.test at test.py:37 | test.py:41:14:41:14 | simple.test at test.py:41 |
|
||||
| test.py:37:13:37:18 | simple.test at test.py:37 | test.py:37:9:37:9 | simple.test at test.py:37 |
|
||||
| test.py:49:17:49:19 | simple.test at test.py:49 | test.py:51:14:51:16 | simple.test at test.py:51 |
|
||||
| test.py:51:14:51:16 | simple.test at test.py:51 | test.py:12:10:12:12 | simple.test at test.py:12 |
|
||||
| test.py:62:9:62:9 | simple.test at test.py:62 | test.py:63:5:63:9 | simple.test at test.py:63 |
|
||||
| test.py:62:13:62:18 | simple.test at test.py:62 | test.py:62:9:62:9 | simple.test at test.py:62 |
|
||||
| test.py:63:5:63:9 | simple.test at test.py:63 | test.py:63:17:63:17 | simple.test at test.py:63 |
|
||||
| test.py:63:17:63:17 | simple.test at test.py:63 | test.py:49:17:49:19 | simple.test at test.py:49 |
|
||||
| test.py:67:9:67:9 | simple.test at test.py:67 | test.py:70:5:70:9 | simple.test at test.py:70 |
|
||||
| test.py:67:13:67:18 | simple.test at test.py:67 | test.py:67:9:67:9 | simple.test at test.py:67 |
|
||||
| test.py:70:5:70:9 | simple.test at test.py:70 | test.py:70:17:70:17 | simple.test at test.py:70 |
|
||||
| test.py:70:17:70:17 | simple.test at test.py:70 | test.py:49:17:49:19 | simple.test at test.py:49 |
|
||||
| test.py:126:9:126:9 | simple.test at test.py:126 | test.py:130:21:130:21 | simple.test at test.py:130 |
|
||||
| test.py:126:13:126:25 | simple.test at test.py:126 | test.py:126:9:126:9 | simple.test at test.py:126 |
|
||||
| test.py:128:9:128:9 | simple.test at test.py:128 | test.py:132:14:132:14 | simple.test at test.py:132 |
|
||||
| test.py:128:13:128:18 | simple.test at test.py:128 | test.py:128:9:128:9 | simple.test at test.py:128 |
|
||||
parents
|
||||
#select
|
||||
| rockpaperscissors.py:13:10:13:17 | ControlFlowNode for SCISSORS | rockpaperscissors.py:13:10:13:17 | scissors at rockpaperscissors.py:13 | rockpaperscissors.py:13:10:13:17 | scissors at rockpaperscissors.py:13 | $@ looses to $@. | rockpaperscissors.py:13:10:13:17 | ControlFlowNode for SCISSORS | scissors | rockpaperscissors.py:13:10:13:17 | ControlFlowNode for SCISSORS | scissors |
|
||||
| rockpaperscissors.py:16:11:16:14 | ControlFlowNode for ROCK | rockpaperscissors.py:16:11:16:14 | rock at rockpaperscissors.py:16 | rockpaperscissors.py:16:11:16:14 | rock at rockpaperscissors.py:16 | $@ looses to $@. | rockpaperscissors.py:16:11:16:14 | ControlFlowNode for ROCK | rock | rockpaperscissors.py:16:11:16:14 | ControlFlowNode for ROCK | rock |
|
||||
| rockpaperscissors.py:26:14:26:14 | ControlFlowNode for y | rockpaperscissors.py:24:9:24:12 | rock at rockpaperscissors.py:24 | rockpaperscissors.py:26:14:26:14 | paper at rockpaperscissors.py:26 | $@ looses to $@. | rockpaperscissors.py:24:9:24:12 | ControlFlowNode for ROCK | rock | rockpaperscissors.py:26:14:26:14 | ControlFlowNode for y | paper |
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
import semmle.python.security.Paths
|
||||
|
||||
from RockPaperScissorConfig config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "$@ looses to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString()
|
|
@ -0,0 +1,76 @@
|
|||
edges
|
||||
| carrier.py:13:9:13:11 | explicit.carrier at carrier.py:13 | carrier.py:14:12:14:14 | explicit.carrier at carrier.py:14 |
|
||||
| carrier.py:14:12:14:14 | explicit.carrier at carrier.py:14 | carrier.py:29:9:29:33 | explicit.carrier at carrier.py:29 |
|
||||
| carrier.py:21:5:21:5 | explicit.carrier at carrier.py:21 | carrier.py:22:10:22:10 | explicit.carrier at carrier.py:22 |
|
||||
| carrier.py:21:9:21:28 | explicit.carrier at carrier.py:21 | carrier.py:21:5:21:5 | explicit.carrier at carrier.py:21 |
|
||||
| carrier.py:22:10:22:10 | explicit.carrier at carrier.py:22 | carrier.py:22:10:22:22 | simple.test at carrier.py:22 |
|
||||
| carrier.py:29:5:29:5 | explicit.carrier at carrier.py:29 | carrier.py:30:10:30:10 | explicit.carrier at carrier.py:30 |
|
||||
| carrier.py:29:9:29:33 | explicit.carrier at carrier.py:29 | carrier.py:29:5:29:5 | explicit.carrier at carrier.py:29 |
|
||||
| carrier.py:29:13:29:32 | explicit.carrier at carrier.py:29 | carrier.py:13:9:13:11 | explicit.carrier at carrier.py:13 |
|
||||
| carrier.py:30:10:30:10 | explicit.carrier at carrier.py:30 | carrier.py:30:10:30:22 | simple.test at carrier.py:30 |
|
||||
| deep.py:2:8:2:10 | simple.test at deep.py:2 | deep.py:3:12:3:14 | simple.test at deep.py:3 |
|
||||
| deep.py:3:12:3:14 | simple.test at deep.py:3 | deep.py:6:12:6:18 | simple.test at deep.py:6 |
|
||||
| deep.py:5:8:5:10 | simple.test at deep.py:5 | deep.py:6:15:6:17 | simple.test at deep.py:6 |
|
||||
| deep.py:6:12:6:18 | simple.test at deep.py:6 | deep.py:9:12:9:18 | simple.test at deep.py:9 |
|
||||
| deep.py:6:15:6:17 | simple.test at deep.py:6 | deep.py:2:8:2:10 | simple.test at deep.py:2 |
|
||||
| deep.py:8:8:8:10 | simple.test at deep.py:8 | deep.py:9:15:9:17 | simple.test at deep.py:9 |
|
||||
| deep.py:9:12:9:18 | simple.test at deep.py:9 | deep.py:12:12:12:18 | simple.test at deep.py:12 |
|
||||
| deep.py:9:15:9:17 | simple.test at deep.py:9 | deep.py:5:8:5:10 | simple.test at deep.py:5 |
|
||||
| deep.py:11:8:11:10 | simple.test at deep.py:11 | deep.py:12:15:12:17 | simple.test at deep.py:12 |
|
||||
| deep.py:12:12:12:18 | simple.test at deep.py:12 | deep.py:15:12:15:18 | simple.test at deep.py:15 |
|
||||
| deep.py:12:15:12:17 | simple.test at deep.py:12 | deep.py:8:8:8:10 | simple.test at deep.py:8 |
|
||||
| deep.py:14:8:14:10 | simple.test at deep.py:14 | deep.py:15:15:15:17 | simple.test at deep.py:15 |
|
||||
| deep.py:15:12:15:18 | simple.test at deep.py:15 | deep.py:18:12:18:18 | simple.test at deep.py:18 |
|
||||
| deep.py:15:15:15:17 | simple.test at deep.py:15 | deep.py:11:8:11:10 | simple.test at deep.py:11 |
|
||||
| deep.py:17:8:17:10 | simple.test at deep.py:17 | deep.py:18:15:18:17 | simple.test at deep.py:18 |
|
||||
| deep.py:18:12:18:18 | simple.test at deep.py:18 | deep.py:20:5:20:14 | simple.test at deep.py:20 |
|
||||
| deep.py:18:15:18:17 | simple.test at deep.py:18 | deep.py:14:8:14:10 | simple.test at deep.py:14 |
|
||||
| deep.py:20:1:20:1 | simple.test at deep.py:20 | deep.py:22:6:22:6 | simple.test at deep.py:22 |
|
||||
| deep.py:20:5:20:14 | simple.test at deep.py:20 | deep.py:20:1:20:1 | simple.test at deep.py:20 |
|
||||
| deep.py:20:8:20:13 | simple.test at deep.py:20 | deep.py:17:8:17:10 | simple.test at deep.py:17 |
|
||||
| rockpaperscissors.py:24:5:24:5 | rock at rockpaperscissors.py:24 | rockpaperscissors.py:25:9:25:9 | rock at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:24:9:24:12 | rock at rockpaperscissors.py:24 | rockpaperscissors.py:24:5:24:5 | rock at rockpaperscissors.py:24 |
|
||||
| rockpaperscissors.py:25:5:25:5 | paper at rockpaperscissors.py:25 | rockpaperscissors.py:26:14:26:14 | paper at rockpaperscissors.py:26 |
|
||||
| rockpaperscissors.py:25:9:25:9 | rock at rockpaperscissors.py:25 | rockpaperscissors.py:25:9:25:16 | scissors at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:25:9:25:16 | scissors at rockpaperscissors.py:25 | rockpaperscissors.py:25:9:25:23 | paper at rockpaperscissors.py:25 |
|
||||
| rockpaperscissors.py:25:9:25:23 | paper at rockpaperscissors.py:25 | rockpaperscissors.py:25:5:25:5 | paper at rockpaperscissors.py:25 |
|
||||
| test.py:6:5:6:5 | simple.test at test.py:6 | test.py:7:10:7:10 | simple.test at test.py:7 |
|
||||
| test.py:6:9:6:14 | simple.test at test.py:6 | test.py:6:5:6:5 | simple.test at test.py:6 |
|
||||
| test.py:12:10:12:12 | simple.test at test.py:12 | test.py:13:10:13:12 | simple.test at test.py:13 |
|
||||
| test.py:20:5:20:5 | simple.test at test.py:20 | test.py:21:10:21:10 | simple.test at test.py:21 |
|
||||
| test.py:20:9:20:14 | simple.test at test.py:20 | test.py:20:5:20:5 | simple.test at test.py:20 |
|
||||
| test.py:21:10:21:10 | simple.test at test.py:21 | test.py:12:10:12:12 | simple.test at test.py:12 |
|
||||
| test.py:37:9:37:9 | simple.test at test.py:37 | test.py:41:14:41:14 | simple.test at test.py:41 |
|
||||
| test.py:37:13:37:18 | simple.test at test.py:37 | test.py:37:9:37:9 | simple.test at test.py:37 |
|
||||
| test.py:49:17:49:19 | simple.test at test.py:49 | test.py:51:14:51:16 | simple.test at test.py:51 |
|
||||
| test.py:51:14:51:16 | simple.test at test.py:51 | test.py:12:10:12:12 | simple.test at test.py:12 |
|
||||
| test.py:62:9:62:9 | simple.test at test.py:62 | test.py:63:5:63:9 | simple.test at test.py:63 |
|
||||
| test.py:62:13:62:18 | simple.test at test.py:62 | test.py:62:9:62:9 | simple.test at test.py:62 |
|
||||
| test.py:63:5:63:9 | simple.test at test.py:63 | test.py:63:17:63:17 | simple.test at test.py:63 |
|
||||
| test.py:63:17:63:17 | simple.test at test.py:63 | test.py:49:17:49:19 | simple.test at test.py:49 |
|
||||
| test.py:67:9:67:9 | simple.test at test.py:67 | test.py:70:5:70:9 | simple.test at test.py:70 |
|
||||
| test.py:67:13:67:18 | simple.test at test.py:67 | test.py:67:9:67:9 | simple.test at test.py:67 |
|
||||
| test.py:70:5:70:9 | simple.test at test.py:70 | test.py:70:17:70:17 | simple.test at test.py:70 |
|
||||
| test.py:70:17:70:17 | simple.test at test.py:70 | test.py:49:17:49:19 | simple.test at test.py:49 |
|
||||
| test.py:72:9:72:11 | simple.test at test.py:72 | test.py:73:12:73:14 | simple.test at test.py:73 |
|
||||
| test.py:73:12:73:14 | simple.test at test.py:73 | test.py:77:9:77:14 | simple.test at test.py:77 |
|
||||
| test.py:76:5:76:5 | simple.test at test.py:76 | test.py:77:13:77:13 | simple.test at test.py:77 |
|
||||
| test.py:76:9:76:14 | simple.test at test.py:76 | test.py:76:5:76:5 | simple.test at test.py:76 |
|
||||
| test.py:77:5:77:5 | simple.test at test.py:77 | test.py:78:10:78:10 | simple.test at test.py:78 |
|
||||
| test.py:77:9:77:14 | simple.test at test.py:77 | test.py:77:5:77:5 | simple.test at test.py:77 |
|
||||
| test.py:77:13:77:13 | simple.test at test.py:77 | test.py:72:9:72:11 | simple.test at test.py:72 |
|
||||
| test.py:126:9:126:9 | simple.test at test.py:126 | test.py:130:21:130:21 | simple.test at test.py:130 |
|
||||
| test.py:126:13:126:25 | simple.test at test.py:126 | test.py:126:9:126:9 | simple.test at test.py:126 |
|
||||
| test.py:128:9:128:9 | simple.test at test.py:128 | test.py:132:14:132:14 | simple.test at test.py:132 |
|
||||
| test.py:128:13:128:18 | simple.test at test.py:128 | test.py:128:9:128:9 | simple.test at test.py:128 |
|
||||
parents
|
||||
#select
|
||||
| deep.py:22:6:22:6 | ControlFlowNode for x | deep.py:20:8:20:13 | simple.test at deep.py:20 | deep.py:22:6:22:6 | simple.test at deep.py:22 | $@ flows to $@. | deep.py:20:8:20:13 | ControlFlowNode for SOURCE | simple.test | deep.py:22:6:22:6 | ControlFlowNode for x | simple.test |
|
||||
| test.py:3:10:3:15 | ControlFlowNode for SOURCE | test.py:3:10:3:15 | simple.test at test.py:3 | test.py:3:10:3:15 | simple.test at test.py:3 | $@ flows to $@. | test.py:3:10:3:15 | ControlFlowNode for SOURCE | simple.test | test.py:3:10:3:15 | ControlFlowNode for SOURCE | simple.test |
|
||||
| test.py:7:10:7:10 | ControlFlowNode for s | test.py:6:9:6:14 | simple.test at test.py:6 | test.py:7:10:7:10 | simple.test at test.py:7 | $@ flows to $@. | test.py:6:9:6:14 | ControlFlowNode for SOURCE | simple.test | test.py:7:10:7:10 | ControlFlowNode for s | simple.test |
|
||||
| test.py:13:10:13:12 | ControlFlowNode for arg | test.py:20:9:20:14 | simple.test at test.py:20 | test.py:13:10:13:12 | simple.test at test.py:13 | $@ flows to $@. | test.py:20:9:20:14 | ControlFlowNode for SOURCE | simple.test | test.py:13:10:13:12 | ControlFlowNode for arg | simple.test |
|
||||
| test.py:13:10:13:12 | ControlFlowNode for arg | test.py:62:13:62:18 | simple.test at test.py:62 | test.py:13:10:13:12 | simple.test at test.py:13 | $@ flows to $@. | test.py:62:13:62:18 | ControlFlowNode for SOURCE | simple.test | test.py:13:10:13:12 | ControlFlowNode for arg | simple.test |
|
||||
| test.py:13:10:13:12 | ControlFlowNode for arg | test.py:67:13:67:18 | simple.test at test.py:67 | test.py:13:10:13:12 | simple.test at test.py:13 | $@ flows to $@. | test.py:67:13:67:18 | ControlFlowNode for SOURCE | simple.test | test.py:13:10:13:12 | ControlFlowNode for arg | simple.test |
|
||||
| test.py:41:14:41:14 | ControlFlowNode for t | test.py:37:13:37:18 | simple.test at test.py:37 | test.py:41:14:41:14 | simple.test at test.py:41 | $@ flows to $@. | test.py:37:13:37:18 | ControlFlowNode for SOURCE | simple.test | test.py:41:14:41:14 | ControlFlowNode for t | simple.test |
|
||||
| test.py:78:10:78:10 | ControlFlowNode for t | test.py:76:9:76:14 | simple.test at test.py:76 | test.py:78:10:78:10 | simple.test at test.py:78 | $@ flows to $@. | test.py:76:9:76:14 | ControlFlowNode for SOURCE | simple.test | test.py:78:10:78:10 | ControlFlowNode for t | simple.test |
|
||||
| test.py:132:14:132:14 | ControlFlowNode for t | test.py:128:13:128:18 | simple.test at test.py:128 | test.py:132:14:132:14 | simple.test at test.py:132 | $@ flows to $@. | test.py:128:13:128:18 | ControlFlowNode for SOURCE | simple.test | test.py:132:14:132:14 | ControlFlowNode for t | simple.test |
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
import semmle.python.security.Paths
|
||||
|
||||
from SimpleConfig config, TaintedPathSource src, TaintedPathSink sink
|
||||
where config.hasFlowPath(src, sink)
|
||||
select sink.getSink(), src, sink, "$@ flows to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString()
|
|
@ -0,0 +1,331 @@
|
|||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
|
||||
|
||||
class SimpleTest extends TaintKind {
|
||||
|
||||
SimpleTest() {
|
||||
this = "simple.test"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SimpleConfig extends TaintTracking::Configuration {
|
||||
|
||||
SimpleConfig() { this = "Simple config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node, TaintKind kind) {
|
||||
node.asCfgNode().(NameNode).getId() = "SOURCE" and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node, TaintKind kind) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK" and
|
||||
node.asCfgNode() = call.getAnArg()
|
||||
) and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node, TaintKind kind) {
|
||||
node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BasicCustomTaint extends TaintKind {
|
||||
|
||||
BasicCustomTaint() {
|
||||
this = "basic.custom"
|
||||
}
|
||||
|
||||
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
|
||||
tonode.(CallNode).getAnArg() = fromnode and
|
||||
tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and
|
||||
result = this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class BasicCustomConfig extends TaintTracking::Configuration {
|
||||
|
||||
BasicCustomConfig() { this = "Basic custom config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node, TaintKind kind) {
|
||||
node.asCfgNode().(NameNode).getId() = "CUSTOM_SOURCE" and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node, TaintKind kind) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "CUSTOM_SINK" and
|
||||
node.asCfgNode() = call.getAnArg()
|
||||
) and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Rock extends TaintKind {
|
||||
|
||||
Rock() { this = "rock" }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name = "prev" and result instanceof Scissors
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Paper extends TaintKind {
|
||||
|
||||
Paper() { this = "paper" }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name = "prev" and result instanceof Rock
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Scissors extends TaintKind {
|
||||
|
||||
Scissors() { this = "scissors" }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name = "prev" and result instanceof Paper
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RockPaperScissorConfig extends TaintTracking::Configuration {
|
||||
|
||||
RockPaperScissorConfig() { this = "Rock-paper-scissors config" }
|
||||
|
||||
|
||||
override predicate isSource(DataFlow::Node node, TaintKind kind) {
|
||||
exists(string name |
|
||||
node.asCfgNode().(NameNode).getId() = name and
|
||||
kind = name.toLowerCase()
|
||||
|
|
||||
name = "ROCK" or name = "PAPER" or name = "SCISSORS"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node, TaintKind kind) {
|
||||
exists(string name |
|
||||
function_param(name, node) |
|
||||
name = "paper" and kind = "rock"
|
||||
or
|
||||
name = "rock" and kind = "scissors"
|
||||
or
|
||||
name = "scissors" and kind = "paper"
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private predicate function_param(string funcname, DataFlow::Node arg) {
|
||||
exists(FunctionObject f |
|
||||
f.getName() = funcname and
|
||||
arg.asCfgNode() = f.getArgumentForCall(_, _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
class TaintCarrier extends TaintKind {
|
||||
|
||||
TaintCarrier() { this = "explicit.carrier" }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name = "get_taint" and result instanceof SimpleTest
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class TaintCarrierConfig extends TaintTracking::Configuration {
|
||||
|
||||
TaintCarrierConfig() { this = "Taint carrier config" }
|
||||
|
||||
override predicate isSource(DataFlow::Node node, TaintKind kind) {
|
||||
node.asCfgNode().(NameNode).getId() = "TAINT_CARRIER_SOURCE" and
|
||||
kind instanceof TaintCarrier
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node node, TaintKind kind) {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "SINK" and
|
||||
node.asCfgNode() = call.getAnArg()
|
||||
) and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node, TaintKind kind) {
|
||||
node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and
|
||||
kind instanceof SimpleTest
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Some more realistic examples */
|
||||
|
||||
abstract class UserInput extends TaintKind {
|
||||
|
||||
bindingset[this]
|
||||
UserInput() { any() }
|
||||
|
||||
}
|
||||
|
||||
class UserInputSource extends TaintSource {
|
||||
|
||||
UserInputSource() {
|
||||
this.(CallNode).getFunction().(NameNode).getId() = "user_input"
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof UserInput
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "user.input.source"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SqlInjectionTaint extends UserInput {
|
||||
|
||||
SqlInjectionTaint() { this = "SQL injection" }
|
||||
|
||||
}
|
||||
|
||||
class CommandInjectionTaint extends UserInput {
|
||||
|
||||
CommandInjectionTaint() { this = "Command injection" }
|
||||
|
||||
}
|
||||
|
||||
class SqlSanitizer extends Sanitizer {
|
||||
|
||||
SqlSanitizer() { this = "SQL sanitizer" }
|
||||
|
||||
/** Holds if `test` shows value to be untainted with `taint` */
|
||||
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
|
||||
exists(FunctionObject f, CallNode call |
|
||||
f.getName() = "isEscapedSql" and
|
||||
test.getTest() = call and
|
||||
call.getAnArg() = test.getSourceVariable().getAUse() and
|
||||
f.getACall() = call and
|
||||
test.getSense() = true
|
||||
) and
|
||||
taint instanceof SqlInjectionTaint
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CommandSanitizer extends Sanitizer {
|
||||
|
||||
CommandSanitizer() { this = "Command sanitizer" }
|
||||
|
||||
/** Holds if `test` shows value to be untainted with `taint` */
|
||||
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
|
||||
exists(FunctionObject f |
|
||||
f.getName() = "isValidCommand" and
|
||||
f.getACall().(CallNode).getAnArg() = test.getSourceVariable().getAUse() and
|
||||
test.getSense() = true
|
||||
) and
|
||||
taint instanceof CommandInjectionTaint
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SqlQuery extends TaintSink {
|
||||
|
||||
SqlQuery() {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "sql_query" and
|
||||
call.getAnArg() = this
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = "SQL query" }
|
||||
|
||||
override predicate sinks(TaintKind taint) {
|
||||
taint instanceof SqlInjectionTaint
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class OsCommand extends TaintSink {
|
||||
|
||||
OsCommand() {
|
||||
exists(CallNode call |
|
||||
call.getFunction().(NameNode).getId() = "os_command" and
|
||||
call.getAnArg() = this
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = "OS command" }
|
||||
|
||||
override predicate sinks(TaintKind taint) {
|
||||
taint instanceof CommandInjectionTaint
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Falsey extends TaintKind {
|
||||
|
||||
Falsey() { this = "falsey" }
|
||||
|
||||
override boolean booleanValue() {
|
||||
result = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FalseySource extends TaintSource {
|
||||
|
||||
FalseySource() {
|
||||
this.(NameNode).getId() = "FALSEY"
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof Falsey
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "falsey.source"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TaintIterable extends TaintKind {
|
||||
|
||||
TaintIterable() {
|
||||
this = "iterable.simple"
|
||||
}
|
||||
|
||||
override TaintKind getTaintForIteration() {
|
||||
result instanceof SimpleTest
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TaintIterableSource extends TaintSource {
|
||||
|
||||
TaintIterableSource() {
|
||||
this.(NameNode).getId() = "ITERABLE_SOURCE"
|
||||
}
|
||||
|
||||
override predicate isSourceOf(TaintKind kind) {
|
||||
kind instanceof TaintIterable
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
fail
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
import python
|
||||
|
||||
|
||||
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
import semmle.python.dataflow.Implementation
|
||||
|
||||
from TaintTrackingImplementation config, TaintTrackingNode src, CallNode call,
|
||||
TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind
|
||||
where config.callWithTaintedArgument(src, call, caller, pyfunc, arg, path, kind)
|
||||
select config, src, call, caller, pyfunc, arg, path, kind
|
|
@ -0,0 +1,9 @@
|
|||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import semmle.python.dataflow.Implementation
|
||||
import TaintLib
|
||||
|
||||
|
||||
from TaintTrackingNode n
|
||||
select n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getPath().toString(), n.getContext().toString()
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
| Rock-paper-scissors config | rockpaperscissors.py:13 | 13 | ControlFlowNode for SCISSORS | scissors |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:16 | 16 | ControlFlowNode for ROCK | rock |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:21 | 21 | ControlFlowNode for y | paper |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:26 | 26 | ControlFlowNode for y | paper |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:31 | 31 | ControlFlowNode for x | rock |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:32 | 32 | ControlFlowNode for y | rock |
|
||||
| Simple config | carrier.py:18 | 18 | ControlFlowNode for Attribute | simple.test |
|
||||
| Simple config | carrier.py:22 | 22 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Simple config | carrier.py:26 | 26 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Simple config | carrier.py:30 | 30 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Simple config | carrier.py:35 | 35 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Simple config | test.py:3 | 3 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:7 | 7 | ControlFlowNode for s | simple.test |
|
||||
| Simple config | test.py:13 | 13 | ControlFlowNode for arg | simple.test |
|
||||
| Simple config | test.py:17 | 17 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:33 | 33 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:41 | 41 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:78 | 78 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:83 | 83 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:89 | 89 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:93 | 93 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:97 | 97 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:101 | 101 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:106 | 106 | ControlFlowNode for Attribute | simple.test |
|
||||
| Simple config | test.py:111 | 111 | ControlFlowNode for Attribute | simple.test |
|
||||
| Simple config | test.py:132 | 132 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:142 | 142 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:153 | 153 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:156 | 156 | ControlFlowNode for unsafe | simple.test |
|
||||
| Simple config | test.py:160 | 160 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:165 | 165 | ControlFlowNode for s | simple.test |
|
||||
| Simple config | test.py:172 | 172 | ControlFlowNode for Subscript | simple.test |
|
||||
| Simple config | test.py:173 | 173 | ControlFlowNode for Subscript | simple.test |
|
||||
| Simple config | test.py:180 | 180 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:182 | 182 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:184 | 184 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:186 | 186 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:197 | 197 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:199 | 199 | ControlFlowNode for t | simple.test |
|
||||
| Simple config | test.py:214 | 214 | ControlFlowNode for x | simple.test |
|
||||
| Taint carrier config | carrier.py:18 | 18 | ControlFlowNode for Attribute | simple.test |
|
||||
| Taint carrier config | carrier.py:22 | 22 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Taint carrier config | carrier.py:26 | 26 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Taint carrier config | carrier.py:30 | 30 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Taint carrier config | carrier.py:35 | 35 | ControlFlowNode for Attribute() | simple.test |
|
||||
| Taint carrier config | test.py:3 | 3 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Taint carrier config | test.py:7 | 7 | ControlFlowNode for s | simple.test |
|
||||
| Taint carrier config | test.py:13 | 13 | ControlFlowNode for arg | simple.test |
|
||||
| Taint carrier config | test.py:17 | 17 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:33 | 33 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:41 | 41 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:78 | 78 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:83 | 83 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:89 | 89 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:93 | 93 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:97 | 97 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:101 | 101 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:106 | 106 | ControlFlowNode for Attribute | simple.test |
|
||||
| Taint carrier config | test.py:111 | 111 | ControlFlowNode for Attribute | simple.test |
|
||||
| Taint carrier config | test.py:132 | 132 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:142 | 142 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:153 | 153 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:156 | 156 | ControlFlowNode for unsafe | simple.test |
|
||||
| Taint carrier config | test.py:160 | 160 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:165 | 165 | ControlFlowNode for s | simple.test |
|
||||
| Taint carrier config | test.py:172 | 172 | ControlFlowNode for Subscript | simple.test |
|
||||
| Taint carrier config | test.py:173 | 173 | ControlFlowNode for Subscript | simple.test |
|
||||
| Taint carrier config | test.py:180 | 180 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:182 | 182 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:184 | 184 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:186 | 186 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:197 | 197 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:199 | 199 | ControlFlowNode for t | simple.test |
|
||||
| Taint carrier config | test.py:214 | 214 | ControlFlowNode for x | simple.test |
|
||||
| Basic custom config | test.py:122 | 122 | ControlFlowNode for t | simple.test |
|
||||
| Basic custom config | test.py:130 | 130 | ControlFlowNode for t | simple.test |
|
||||
| Basic custom config | test.py:140 | 140 | ControlFlowNode for t | simple.test |
|
||||
| Basic custom config | test.py:151 | 151 | ControlFlowNode for t | simple.test |
|
|
@ -0,0 +1,8 @@
|
|||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
|
||||
from TaintTracking::Configuration config, DataFlow::Node sink, TaintKind kind
|
||||
|
||||
where config.isSink(sink, kind)
|
||||
select config, sink.getLocation().toString(), sink.getLocation().getStartLine(), sink.toString(), kind
|
|
@ -0,0 +1,37 @@
|
|||
| Rock-paper-scissors config | rockpaperscissors.py:13 | 13 | ControlFlowNode for SCISSORS | scissors |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:16 | 16 | ControlFlowNode for ROCK | rock |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:19 | 19 | ControlFlowNode for ROCK | rock |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:24 | 24 | ControlFlowNode for ROCK | rock |
|
||||
| Rock-paper-scissors config | rockpaperscissors.py:29 | 29 | ControlFlowNode for SCISSORS | scissors |
|
||||
| Simple config | carrier.py:17 | 17 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | carrier.py:25 | 25 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | deep.py:20 | 20 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | module.py:3 | 3 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | module.py:7 | 7 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | module.py:10 | 10 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:3 | 3 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:6 | 6 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:10 | 10 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:20 | 20 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:31 | 31 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:37 | 37 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:62 | 62 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:67 | 67 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:76 | 76 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:128 | 128 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:138 | 138 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:148 | 148 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:159 | 159 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:163 | 163 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:168 | 168 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:169 | 169 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:178 | 178 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:195 | 195 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Simple config | test.py:208 | 208 | ControlFlowNode for SOURCE | simple.test |
|
||||
| Taint carrier config | carrier.py:21 | 21 | ControlFlowNode for TAINT_CARRIER_SOURCE | explicit.carrier |
|
||||
| Taint carrier config | carrier.py:29 | 29 | ControlFlowNode for TAINT_CARRIER_SOURCE | explicit.carrier |
|
||||
| Taint carrier config | carrier.py:33 | 33 | ControlFlowNode for TAINT_CARRIER_SOURCE | explicit.carrier |
|
||||
| Basic custom config | test.py:120 | 120 | ControlFlowNode for CUSTOM_SOURCE | simple.test |
|
||||
| Basic custom config | test.py:126 | 126 | ControlFlowNode for CUSTOM_SOURCE | simple.test |
|
||||
| Basic custom config | test.py:136 | 136 | ControlFlowNode for CUSTOM_SOURCE | simple.test |
|
||||
| Basic custom config | test.py:146 | 146 | ControlFlowNode for CUSTOM_SOURCE | simple.test |
|
|
@ -0,0 +1,8 @@
|
|||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
|
||||
from TaintTracking::Configuration config, DataFlow::Node source, TaintKind kind
|
||||
|
||||
where config.isSource(source, kind)
|
||||
select config, source.getLocation().toString(), source.getLocation().getStartLine(), source.toString(), kind
|
|
@ -0,0 +1,13 @@
|
|||
import python
|
||||
import semmle.python.security.TaintTracking
|
||||
import TaintLib
|
||||
import semmle.python.dataflow.Implementation
|
||||
|
||||
|
||||
from TaintTrackingNode n, TaintTrackingNode s, TaintTracking::Configuration config
|
||||
where s = n.getASuccessor() and config = n.getConfiguration()
|
||||
select
|
||||
config + ":",
|
||||
n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getContext(),
|
||||
" --> ",
|
||||
s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), s.getContext()
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
class ImplicitCarrier(object):
|
||||
|
||||
def __init__(self, arg):
|
||||
self.attr = arg
|
||||
|
||||
def set_attr(self, arg):
|
||||
self.attr = arg
|
||||
|
||||
def get_attr(self):
|
||||
return self.attr
|
||||
|
||||
def hub(arg):
|
||||
return arg
|
||||
|
||||
def test1():
|
||||
c = ImplicitCarrier(SOURCE)
|
||||
SINK(c.attr)
|
||||
|
||||
def test2():
|
||||
c = TAINT_CARRIER_SOURCE
|
||||
SINK(c.get_taint())
|
||||
|
||||
def test3():
|
||||
c = hub(ImplicitCarrier(SOURCE))
|
||||
SINK(c.get_attr())
|
||||
|
||||
def test4():
|
||||
c = hub(TAINT_CARRIER_SOURCE)
|
||||
SINK(c.get_taint())
|
||||
|
||||
def test5():
|
||||
c = ImplicitCarrier(TAINT_CARRIER_SOURCE)
|
||||
x = c.attr
|
||||
SINK(x.get_taint())
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
def f1(arg):
|
||||
return arg
|
||||
|
||||
def f2(arg):
|
||||
return f1(arg)
|
||||
|
||||
def f3(arg):
|
||||
return f2(arg)
|
||||
|
||||
def f4(arg):
|
||||
return f3(arg)
|
||||
|
||||
def f5(arg):
|
||||
return f4(arg)
|
||||
|
||||
def f6(arg):
|
||||
return f5(arg)
|
||||
|
||||
x = f6(SOURCE)
|
||||
|
||||
SINK(x)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
dangerous = SOURCE
|
||||
safe = "safe"
|
||||
|
||||
def dangerous_func():
|
||||
return SOURCE
|
||||
|
||||
|
||||
safe2 = SOURCE
|
||||
safe2 = "safe"
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
|
||||
def rock(arg):
|
||||
"SCISSORS are vulnerable"
|
||||
|
||||
def paper(arg):
|
||||
"ROCK is vulnerable"
|
||||
|
||||
def scissors(arg):
|
||||
"PAPER is vulnerable"
|
||||
|
||||
def test1():
|
||||
rock(SCISSORS)
|
||||
|
||||
def test2():
|
||||
paper(ROCK)
|
||||
|
||||
def test3():
|
||||
x = ROCK
|
||||
y = x.prev() #scissors
|
||||
scissors(y)
|
||||
|
||||
def test4():
|
||||
x = ROCK
|
||||
y = x.prev().prev() # paper
|
||||
scissors(y)
|
||||
|
||||
def test5():
|
||||
x = SCISSORS
|
||||
y = x.prev() # paper
|
||||
paper(x)
|
||||
paper(y)
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#Sanitizer functions
|
||||
def isEscapedSql(arg): pass
|
||||
|
||||
def isValidCommand(arg): pass
|
||||
|
||||
|
||||
def sql_inject1():
|
||||
x = user_input()
|
||||
if isEscapedSql(x):
|
||||
sql_query(x) # Safe
|
||||
else:
|
||||
sql_query(x) # DANGEROUS
|
||||
|
||||
def command_inject1():
|
||||
x = user_input()
|
||||
if isValidCommand(x):
|
||||
os_command(x) # Safe
|
||||
else:
|
||||
os_command(x) # DANGEROUS
|
||||
|
||||
|
||||
def sql_inject2():
|
||||
x = user_input()
|
||||
if notASanitizer(x):
|
||||
sql_query(x) # DANGEROUS
|
||||
else:
|
||||
sql_query(x) # DANGEROUS
|
||||
|
||||
def command_inject2():
|
||||
x = user_input()
|
||||
if notASanitizer(x):
|
||||
os_command(x) # DANGEROUS
|
||||
else:
|
||||
os_command(x) # DANGEROUS
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
|
||||
def test1():
|
||||
SINK(SOURCE)
|
||||
|
||||
def test2():
|
||||
s = SOURCE
|
||||
SINK(s)
|
||||
|
||||
def source():
|
||||
return SOURCE
|
||||
|
||||
def sink(arg):
|
||||
SINK(arg)
|
||||
|
||||
def test3():
|
||||
t = source()
|
||||
SINK(t)
|
||||
|
||||
def test4():
|
||||
t = SOURCE
|
||||
sink(t)
|
||||
|
||||
def test5():
|
||||
t = source()
|
||||
sink(t)
|
||||
|
||||
def test6(cond):
|
||||
if cond:
|
||||
t = "Safe"
|
||||
else:
|
||||
t = SOURCE
|
||||
if cond:
|
||||
SINK(t)
|
||||
|
||||
def test7(cond):
|
||||
if cond:
|
||||
t = SOURCE
|
||||
else:
|
||||
t = "Safe"
|
||||
if cond:
|
||||
SINK(t)
|
||||
|
||||
def source2(arg):
|
||||
return source(arg)
|
||||
|
||||
def sink2(arg):
|
||||
sink(arg)
|
||||
|
||||
def sink3(cond, arg):
|
||||
if cond:
|
||||
sink(arg)
|
||||
|
||||
def test8(cond):
|
||||
t = source2()
|
||||
sink2(t)
|
||||
|
||||
#False positive
|
||||
def test9(cond):
|
||||
if cond:
|
||||
t = "Safe"
|
||||
else:
|
||||
t = SOURCE
|
||||
sink3(cond, t)
|
||||
|
||||
def test10(cond):
|
||||
if cond:
|
||||
t = SOURCE
|
||||
else:
|
||||
t = "Safe"
|
||||
sink3(cond, t)
|
||||
|
||||
def hub(arg):
|
||||
return arg
|
||||
|
||||
def test11():
|
||||
t = SOURCE
|
||||
t = hub(t)
|
||||
SINK(t)
|
||||
|
||||
def test12():
|
||||
t = "safe"
|
||||
t = hub(t)
|
||||
SINK(t)
|
||||
|
||||
import module
|
||||
|
||||
def test13():
|
||||
t = module.dangerous
|
||||
SINK(t)
|
||||
|
||||
def test14():
|
||||
t = module.safe
|
||||
SINK(t)
|
||||
|
||||
def test15():
|
||||
t = module.safe2
|
||||
SINK(t)
|
||||
|
||||
def test16():
|
||||
t = module.dangerous_func()
|
||||
SINK(t)
|
||||
|
||||
class C(object): pass
|
||||
|
||||
def x_sink(arg):
|
||||
SINK(arg.x)
|
||||
|
||||
def test17():
|
||||
t = C()
|
||||
t.x = module.dangerous
|
||||
SINK(t.x)
|
||||
|
||||
def test18():
|
||||
t = C()
|
||||
t.x = module.dangerous
|
||||
t = hub(t)
|
||||
x_sink(t)
|
||||
|
||||
def test19():
|
||||
t = CUSTOM_SOURCE
|
||||
t = hub(TAINT_FROM_ARG(t))
|
||||
CUSTOM_SINK(t)
|
||||
|
||||
def test20(cond):
|
||||
if cond:
|
||||
t = CUSTOM_SOURCE
|
||||
else:
|
||||
t = SOURCE
|
||||
if cond:
|
||||
CUSTOM_SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
|
||||
def test21(cond):
|
||||
if cond:
|
||||
t = CUSTOM_SOURCE
|
||||
else:
|
||||
t = SOURCE
|
||||
if not cond:
|
||||
CUSTOM_SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
|
||||
def test22(cond):
|
||||
if cond:
|
||||
t = CUSTOM_SOURCE
|
||||
else:
|
||||
t = SOURCE
|
||||
t = TAINT_FROM_ARG(t)
|
||||
if cond:
|
||||
CUSTOM_SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
|
||||
from module import dangerous as unsafe
|
||||
SINK(unsafe)
|
||||
|
||||
def test23():
|
||||
with SOURCE as t:
|
||||
SINK(t)
|
||||
|
||||
def test24():
|
||||
s = SOURCE
|
||||
SANITIZE(s)
|
||||
SINK(s)
|
||||
|
||||
def test_update_extend(x, y):
|
||||
l = [SOURCE]
|
||||
d = {"key" : SOURCE}
|
||||
x.extend(l)
|
||||
y.update(d)
|
||||
SINK(x[0])
|
||||
SINK(y["key"])
|
||||
l2 = list(l)
|
||||
d2 = dict(d)
|
||||
|
||||
def test_truth():
|
||||
t = SOURCE
|
||||
if t:
|
||||
SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
if not t:
|
||||
SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
|
||||
def test_early_exit():
|
||||
t = FALSEY
|
||||
if not t:
|
||||
return
|
||||
t
|
||||
|
||||
def flow_through_type_test_if_no_class():
|
||||
t = SOURCE
|
||||
if isinstance(t, str):
|
||||
SINK(t)
|
||||
else:
|
||||
SINK(t)
|
||||
|
||||
def flow_in_iteration():
|
||||
t = ITERABLE_SOURCE
|
||||
for i in t:
|
||||
i
|
||||
return i
|
||||
|
||||
def flow_in_generator():
|
||||
seq = [SOURCE]
|
||||
for i in seq:
|
||||
yield i
|
||||
|
||||
def flow_from_generator():
|
||||
for x in flow_in_generator():
|
||||
SINK(x)
|
||||
|
Загрузка…
Ссылка в новой задаче