Python taint-tracking. Add some tests and fix up various parts of the implementation.

This commit is contained in:
Mark Shannon 2019-07-30 16:18:50 +01:00
Родитель eed2090168
Коммит 74f1dd3ec0
22 изменённых файлов: 1045 добавлений и 42 удалений

Просмотреть файл

@ -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)