Merge pull request #4700 from RasmusWL/python-add-code-injection-FP

Approved by tausbn
This commit is contained in:
CodeQL CI
2020-12-02 16:29:21 +00:00
committed by GitHub
19 changed files with 349 additions and 98 deletions

View File

@@ -0,0 +1,27 @@
| test_string_const_compare.py:16 | ok | test_eq | ts |
| test_string_const_compare.py:18 | ok | test_eq | ts |
| test_string_const_compare.py:20 | ok | test_eq | ts |
| test_string_const_compare.py:27 | ok | test_eq_unsafe | ts |
| test_string_const_compare.py:29 | ok | test_eq_unsafe | ts |
| test_string_const_compare.py:35 | fail | test_eq_with_or | ts |
| test_string_const_compare.py:37 | ok | test_eq_with_or | ts |
| test_string_const_compare.py:43 | ok | test_non_eq1 | ts |
| test_string_const_compare.py:45 | ok | test_non_eq1 | ts |
| test_string_const_compare.py:51 | ok | test_non_eq2 | ts |
| test_string_const_compare.py:53 | fail | test_non_eq2 | ts |
| test_string_const_compare.py:59 | ok | test_in_list | ts |
| test_string_const_compare.py:61 | ok | test_in_list | ts |
| test_string_const_compare.py:67 | ok | test_in_tuple | ts |
| test_string_const_compare.py:69 | ok | test_in_tuple | ts |
| test_string_const_compare.py:75 | ok | test_in_set | ts |
| test_string_const_compare.py:77 | ok | test_in_set | ts |
| test_string_const_compare.py:83 | ok | test_in_unsafe1 | ts |
| test_string_const_compare.py:85 | ok | test_in_unsafe1 | ts |
| test_string_const_compare.py:91 | ok | test_in_unsafe2 | ts |
| test_string_const_compare.py:93 | ok | test_in_unsafe2 | ts |
| test_string_const_compare.py:99 | ok | test_not_in1 | ts |
| test_string_const_compare.py:101 | ok | test_not_in1 | ts |
| test_string_const_compare.py:107 | ok | test_not_in2 | ts |
| test_string_const_compare.py:109 | fail | test_not_in2 | ts |
| test_string_const_compare.py:119 | fail | test_eq_thorugh_func | ts |
| test_string_const_compare.py:121 | ok | test_eq_thorugh_func | ts |

View File

@@ -0,0 +1,8 @@
import experimental.dataflow.tainttracking.TestTaintLib
import semmle.python.dataflow.new.BarrierGuards
class CustomSanitizerOverrides extends TestTaintTrackingConfiguration {
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof StringConstCompare
}
}

View File

@@ -0,0 +1,138 @@
# Add taintlib to PATH so it can be imported during runtime without any hassle
import sys; import os; sys.path.append(os.path.dirname(os.path.dirname((__file__))))
from taintlib import *
# This has no runtime impact, but allows autocomplete to work
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..taintlib import *
# Actual tests
def test_eq():
ts = TAINTED_STRING
if ts == "safe":
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
# ts should still be tainted after exiting the if block
ensure_tainted(ts)
def test_eq_unsafe(x="foo"):
"""This test-case might seem strange, but it was a FP in our old points-to based analysis."""
ts = TAINTED_STRING
if ts == ts:
ensure_tainted(ts)
if ts == x:
ensure_tainted(ts)
def test_eq_with_or():
ts = TAINTED_STRING
if ts == "safe" or ts == "also_safe":
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
def test_non_eq1():
ts = TAINTED_STRING
if ts != "safe":
ensure_tainted(ts)
else:
ensure_not_tainted(ts)
def test_non_eq2():
ts = TAINTED_STRING
if not ts == "safe":
ensure_tainted(ts)
else:
ensure_not_tainted(ts)
def test_in_list():
ts = TAINTED_STRING
if ts in ["safe", "also_safe"]:
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
def test_in_tuple():
ts = TAINTED_STRING
if ts in ("safe", "also_safe"):
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
def test_in_set():
ts = TAINTED_STRING
if ts in {"safe", "also_safe"}:
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
def test_in_unsafe1(xs):
ts = TAINTED_STRING
if ts in xs:
ensure_tainted(ts)
else:
ensure_tainted(ts)
def test_in_unsafe2(x):
ts = TAINTED_STRING
if ts in ["safe", x]:
ensure_tainted(ts)
else:
ensure_tainted(ts)
def test_not_in1():
ts = TAINTED_STRING
if ts not in ["safe", "also_safe"]:
ensure_tainted(ts)
else:
ensure_not_tainted(ts)
def test_not_in2():
ts = TAINTED_STRING
if not ts in ["safe", "also_safe"]:
ensure_tainted(ts)
else:
ensure_not_tainted(ts)
def is_safe(x):
return x == "safe"
def test_eq_thorugh_func():
ts = TAINTED_STRING
if is_safe(ts):
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
# Make tests runable
test_eq()
test_eq_unsafe()
test_eq_with_or()
test_non_eq1()
test_non_eq2()
test_in_list()
test_in_tuple()
test_in_set()
test_in_unsafe1(["unsafe", "foo"])
test_in_unsafe2("unsafe")
test_not_in1()
test_not_in2()
test_eq_thorugh_func()

View File

@@ -4,8 +4,47 @@ test_taint
| test.py:38 | ok | test_custom_sanitizer_guard | s |
| test.py:40 | ok | test_custom_sanitizer_guard | s |
| test.py:51 | ok | test_escape | s2 |
| test_logical.py:30 | ok | test_basic | s |
| test_logical.py:32 | ok | test_basic | s |
| test_logical.py:35 | ok | test_basic | s |
| test_logical.py:37 | fail | test_basic | s |
| test_logical.py:45 | ok | test_or | s |
| test_logical.py:47 | ok | test_or | s |
| test_logical.py:51 | ok | test_or | s |
| test_logical.py:53 | ok | test_or | s |
| test_logical.py:57 | ok | test_or | s |
| test_logical.py:59 | ok | test_or | s |
| test_logical.py:67 | ok | test_and | s |
| test_logical.py:69 | ok | test_and | s |
| test_logical.py:73 | ok | test_and | s |
| test_logical.py:75 | ok | test_and | s |
| test_logical.py:79 | ok | test_and | s |
| test_logical.py:81 | fail | test_and | s |
| test_logical.py:89 | fail | test_tricky | s |
| test_logical.py:93 | fail | test_tricky | s_ |
| test_logical.py:100 | fail | test_nesting_not | s |
| test_logical.py:102 | ok | test_nesting_not | s |
| test_logical.py:105 | ok | test_nesting_not | s |
| test_logical.py:107 | fail | test_nesting_not | s |
| test_logical.py:116 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:118 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:121 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:123 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:126 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:128 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:137 | fail | test_with_return | s |
| test_logical.py:146 | fail | test_with_exception | s |
isSanitizer
| TestTaintTrackingConfiguration | test.py:21:39:21:39 | ControlFlowNode for s |
| TestTaintTrackingConfiguration | test.py:50:10:50:29 | ControlFlowNode for emulated_escaping() |
isSanitizerGuard
| TestTaintTrackingConfiguration | test.py:35:8:35:26 | ControlFlowNode for emulated_is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:29:8:29:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:44:8:44:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:50:12:50:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:66:8:66:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:72:12:72:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:92:8:92:17 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:115:12:115:21 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:120:16:120:25 | ControlFlowNode for is_safe() |
| TestTaintTrackingConfiguration | test_logical.py:125:20:125:29 | ControlFlowNode for is_safe() |

View File

@@ -1,7 +1,9 @@
import experimental.dataflow.tainttracking.TestTaintLib
class IsSafeCheck extends DataFlow::BarrierGuard {
IsSafeCheck() { this.(CallNode).getNode().getFunc().(Name).getId() = "emulated_is_safe" }
IsSafeCheck() {
this.(CallNode).getNode().getFunc().(Name).getId() in ["is_safe", "emulated_is_safe"]
}
override predicate checks(ControlFlowNode node, boolean branch) {
node = this.(CallNode).getAnArg() and

View File

@@ -128,6 +128,23 @@ def test_nesting_not_with_and_true():
ensure_not_tainted(s)
def test_with_return():
s = TAINTED_STRING
if not is_safe(s):
return
ensure_not_tainted(s)
def test_with_exception():
s = TAINTED_STRING
if not is_safe(s):
raise Exception("unsafe")
ensure_not_tainted(s)
# Make tests runable
test_basic()
@@ -136,3 +153,8 @@ test_and()
test_tricky()
test_nesting_not()
test_nesting_not_with_and_true()
test_with_return()
try:
test_with_exception()
except:
pass

View File

@@ -1,37 +0,0 @@
| test_logical.py:30 | fail | test_basic | s |
| test_logical.py:32 | ok | test_basic | s |
| test_logical.py:35 | ok | test_basic | s |
| test_logical.py:37 | fail | test_basic | s |
| test_logical.py:45 | ok | test_or | s |
| test_logical.py:47 | ok | test_or | s |
| test_logical.py:51 | ok | test_or | s |
| test_logical.py:53 | ok | test_or | s |
| test_logical.py:57 | ok | test_or | s |
| test_logical.py:59 | ok | test_or | s |
| test_logical.py:67 | fail | test_and | s |
| test_logical.py:69 | ok | test_and | s |
| test_logical.py:73 | ok | test_and | s |
| test_logical.py:75 | fail | test_and | s |
| test_logical.py:79 | ok | test_and | s |
| test_logical.py:81 | fail | test_and | s |
| test_logical.py:89 | fail | test_tricky | s |
| test_logical.py:93 | fail | test_tricky | s_ |
| test_logical.py:100 | fail | test_nesting_not | s |
| test_logical.py:102 | ok | test_nesting_not | s |
| test_logical.py:105 | ok | test_nesting_not | s |
| test_logical.py:107 | fail | test_nesting_not | s |
| test_logical.py:116 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:118 | fail | test_nesting_not_with_and_true | s |
| test_logical.py:121 | fail | test_nesting_not_with_and_true | s |
| test_logical.py:123 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:126 | ok | test_nesting_not_with_and_true | s |
| test_logical.py:128 | fail | test_nesting_not_with_and_true | s |
| test_string_eq.py:16 | fail | const_eq_clears_taint | ts |
| test_string_eq.py:18 | ok | const_eq_clears_taint | ts |
| test_string_eq.py:20 | ok | const_eq_clears_taint | ts |
| test_string_eq.py:27 | fail | const_eq_clears_taint2 | ts |
| test_string_eq.py:33 | ok | non_const_eq_preserves_taint | ts |
| test_string_eq.py:35 | ok | non_const_eq_preserves_taint | ts |
| test_string_eq.py:45 | fail | const_eq_through_func | ts |
| test_string_eq.py:47 | ok | const_eq_through_func | ts |
| test_string_eq.py:49 | ok | const_eq_through_func | ts |

View File

@@ -1 +0,0 @@
import experimental.dataflow.tainttracking.TestTaintLib

View File

@@ -1,56 +0,0 @@
# Add taintlib to PATH so it can be imported during runtime without any hassle
import sys; import os; sys.path.append(os.path.dirname(os.path.dirname((__file__))))
from taintlib import *
# This has no runtime impact, but allows autocomplete to work
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..taintlib import *
# Actual tests
def const_eq_clears_taint():
ts = TAINTED_STRING
if ts == "safe":
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
# ts should still be tainted after exiting the if block
ensure_tainted(ts)
def const_eq_clears_taint2():
ts = TAINTED_STRING
if ts != "safe":
return
ensure_not_tainted(ts)
def non_const_eq_preserves_taint(x="foo"):
ts = TAINTED_STRING
if ts == ts:
ensure_tainted(ts)
if ts == x:
ensure_tainted(ts)
def is_safe(x):
return x == "safe"
def const_eq_through_func():
ts = TAINTED_STRING
if is_safe(ts):
ensure_not_tainted(ts)
else:
ensure_tainted(ts)
# ts should still be tainted after exiting the if block
ensure_tainted(ts)
# Make tests runable
const_eq_clears_taint()
const_eq_clears_taint2()
non_const_eq_preserves_taint()