From e8190d9a7b66c16fbd61766b794df361a2ecf00c Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Tue, 18 Jun 2019 16:11:02 +0100 Subject: [PATCH] Python: Track taint through 'yield' expressions. --- .../semmle/python/security/TaintTracking.qll | 22 +++++++++++++++++++ .../taint/general/TestDefn.expected | 6 +++++ .../taint/general/TestNode.expected | 8 +++++++ .../taint/general/TestSink.expected | 1 + .../taint/general/TestSource.expected | 1 + .../taint/general/TestStep.expected | 7 ++++++ .../taint/general/TestVar.expected | 6 +++++ .../test/library-tests/taint/general/test.py | 9 ++++++++ 8 files changed, 60 insertions(+) diff --git a/python/ql/src/semmle/python/security/TaintTracking.qll b/python/ql/src/semmle/python/security/TaintTracking.qll index b6ae74c8270..d71fb08e365 100755 --- a/python/ql/src/semmle/python/security/TaintTracking.qll +++ b/python/ql/src/semmle/python/security/TaintTracking.qll @@ -875,6 +875,8 @@ library module TaintFlowImplementation { or iteration_step(fromnode, totaint, tocontext, tonode) or + yield_step(fromnode, totaint, tocontext, tonode) + or exists(DataFlowNode fromnodenode | fromnodenode = fromnode.getNode() and ( @@ -1065,6 +1067,26 @@ library module TaintFlowImplementation { ) } + predicate yield_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, CallNode call) { + exists(PyFunctionObject func | + func.getFunction().isGenerator() and + func.getACall() = call and + ( + fromnode.getContext() = tocontext.getCallee(call) + or + fromnode.getContext() = tocontext and tocontext = TTop() + ) and + exists(Yield yield | + yield.getScope() = func.getFunction() and + yield.getValue() = fromnode.getNode().getNode() + ) and + exists(SequenceKind seq | + seq.getItem() = fromnode.getTaintKind() and + totaint = fromnode.getTrackedValue().toKind(seq) + ) + ) + } + predicate call_taint_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, CallNode call) { exists(string name | call.getFunction().(AttrNode).getObject(name) = fromnode.getNode() and diff --git a/python/ql/test/library-tests/taint/general/TestDefn.expected b/python/ql/test/library-tests/taint/general/TestDefn.expected index 59887e635ee..8c41526f516 100644 --- a/python/ql/test/library-tests/taint/general/TestDefn.expected +++ b/python/ql/test/library-tests/taint/general/TestDefn.expected @@ -183,3 +183,9 @@ | test.py:202 | ITERABLE_SOURCE | test.py:202 | Taint iterable.simple | ITERABLE_SOURCE | | test.py:203 | IterationDefinition | test.py:203 | Taint simple.test | i | | test.py:203 | phi(i_0, i_2) | test.py:203 | Taint simple.test | i | +| test.py:208 | List | test.py:208 | Taint [simple.test] | List | +| test.py:209 | IterationDefinition | test.py:209 | Taint simple.test | i | +| test.py:209 | phi(i_0, i_2) | test.py:209 | Taint simple.test | i | +| test.py:213 | IterationDefinition | test.py:213 | Taint simple.test | x | +| test.py:213 | phi(x_2, x_3) | test.py:213 | Taint simple.test | x | +| test.py:214 | ArgumentRefinement(x_1) | test.py:213 | Taint simple.test | x | diff --git a/python/ql/test/library-tests/taint/general/TestNode.expected b/python/ql/test/library-tests/taint/general/TestNode.expected index ffefa3e3f5a..7e2340dca46 100644 --- a/python/ql/test/library-tests/taint/general/TestNode.expected +++ b/python/ql/test/library-tests/taint/general/TestNode.expected @@ -67,6 +67,9 @@ | Taint [simple.test] | test.py:172 | x | | | Taint [simple.test] | test.py:174 | l | | | Taint [simple.test] | test.py:174 | list() | | +| Taint [simple.test] | test.py:208 | List | | +| Taint [simple.test] | test.py:209 | seq | | +| Taint [simple.test] | test.py:213 | flow_in_generator() | | | Taint basic.custom | test.py:72 | arg | test.py:121 | | Taint basic.custom | test.py:73 | arg | test.py:121 | | Taint basic.custom | test.py:120 | CUSTOM_SOURCE | | @@ -231,6 +234,11 @@ | Taint simple.test | test.py:203 | i | | | Taint simple.test | test.py:204 | i | | | Taint simple.test | test.py:205 | i | | +| Taint simple.test | test.py:208 | SOURCE | | +| Taint simple.test | test.py:209 | i | | +| Taint simple.test | test.py:210 | i | | +| Taint simple.test | test.py:213 | x | | +| Taint simple.test | test.py:214 | x | | | Taint {simple.test} | test.py:169 | Dict | | | Taint {simple.test} | test.py:171 | d | | | Taint {simple.test} | test.py:173 | y | | diff --git a/python/ql/test/library-tests/taint/general/TestSink.expected b/python/ql/test/library-tests/taint/general/TestSink.expected index c8a64464b49..4ae2eb46b36 100644 --- a/python/ql/test/library-tests/taint/general/TestSink.expected +++ b/python/ql/test/library-tests/taint/general/TestSink.expected @@ -36,3 +36,4 @@ | simple.test | test.py:178 | 186 | t | simple.test | | simple.test | test.py:195 | 197 | t | simple.test | | simple.test | test.py:195 | 199 | t | simple.test | +| simple.test | test.py:208 | 214 | x | simple.test | diff --git a/python/ql/test/library-tests/taint/general/TestSource.expected b/python/ql/test/library-tests/taint/general/TestSource.expected index c2c295f56a8..3d37d0f497b 100644 --- a/python/ql/test/library-tests/taint/general/TestSource.expected +++ b/python/ql/test/library-tests/taint/general/TestSource.expected @@ -44,3 +44,4 @@ | test.py:189 | FALSEY | falsey | | test.py:195 | SOURCE | simple.test | | test.py:202 | ITERABLE_SOURCE | iterable.simple | +| test.py:208 | SOURCE | simple.test | diff --git a/python/ql/test/library-tests/taint/general/TestStep.expected b/python/ql/test/library-tests/taint/general/TestStep.expected index d38e062741b..3ba461a1d69 100644 --- a/python/ql/test/library-tests/taint/general/TestStep.expected +++ b/python/ql/test/library-tests/taint/general/TestStep.expected @@ -59,6 +59,9 @@ | Taint [simple.test] | test.py:170 | l | | --> | Taint [simple.test] | test.py:172 | x | | | Taint [simple.test] | test.py:172 | x | | --> | Taint simple.test | test.py:172 | Subscript | | | Taint [simple.test] | test.py:174 | l | | --> | Taint [simple.test] | test.py:174 | list() | | +| Taint [simple.test] | test.py:208 | List | | --> | Taint [simple.test] | test.py:209 | seq | | +| Taint [simple.test] | test.py:209 | seq | | --> | Taint simple.test | test.py:209 | i | | +| Taint [simple.test] | test.py:213 | flow_in_generator() | | --> | Taint simple.test | test.py:213 | x | | | Taint basic.custom | test.py:72 | arg | test.py:121 | --> | Taint basic.custom | test.py:73 | arg | test.py:121 | | Taint basic.custom | test.py:73 | arg | test.py:121 | --> | Taint basic.custom | test.py:121 | hub() | | | Taint basic.custom | test.py:120 | CUSTOM_SOURCE | | --> | Taint basic.custom | test.py:121 | t | | @@ -185,6 +188,10 @@ | Taint simple.test | test.py:195 | SOURCE | | --> | Taint simple.test | test.py:199 | t | | | Taint simple.test | test.py:203 | i | | --> | Taint simple.test | test.py:204 | i | | | Taint simple.test | test.py:203 | i | | --> | Taint simple.test | test.py:205 | i | | +| Taint simple.test | test.py:208 | SOURCE | | --> | Taint [simple.test] | test.py:208 | List | | +| Taint simple.test | test.py:209 | i | | --> | Taint simple.test | test.py:210 | i | | +| Taint simple.test | test.py:210 | i | | --> | Taint [simple.test] | test.py:213 | flow_in_generator() | | +| Taint simple.test | test.py:213 | x | | --> | Taint simple.test | test.py:214 | x | | | Taint {simple.test} | test.py:169 | Dict | | --> | Taint {simple.test} | test.py:171 | d | | | Taint {simple.test} | test.py:169 | Dict | | --> | Taint {simple.test} | test.py:175 | d | | | Taint {simple.test} | test.py:171 | d | | --> | Taint {simple.test} | test.py:173 | y | | diff --git a/python/ql/test/library-tests/taint/general/TestVar.expected b/python/ql/test/library-tests/taint/general/TestVar.expected index be77dd40b4b..8e1a31dc410 100644 --- a/python/ql/test/library-tests/taint/general/TestVar.expected +++ b/python/ql/test/library-tests/taint/general/TestVar.expected @@ -185,3 +185,9 @@ | test.py:202 | t_0 | test.py:202 | Taint iterable.simple | ITERABLE_SOURCE | | test.py:203 | i_1 | test.py:203 | Taint simple.test | i | | test.py:203 | i_2 | test.py:203 | Taint simple.test | i | +| test.py:208 | seq_0 | test.py:208 | Taint [simple.test] | List | +| test.py:209 | i_1 | test.py:209 | Taint simple.test | i | +| test.py:209 | i_2 | test.py:209 | Taint simple.test | i | +| test.py:213 | x_0 | test.py:213 | Taint simple.test | x | +| test.py:213 | x_1 | test.py:213 | Taint simple.test | x | +| test.py:214 | x_2 | test.py:213 | Taint simple.test | x | diff --git a/python/ql/test/library-tests/taint/general/test.py b/python/ql/test/library-tests/taint/general/test.py index 9b2256fba51..8ca23aff606 100644 --- a/python/ql/test/library-tests/taint/general/test.py +++ b/python/ql/test/library-tests/taint/general/test.py @@ -204,3 +204,12 @@ def flow_in_iteration(): 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) +