Merge remote-tracking branch 'upstream/main' into better-syntax-for-false-positives-and-negatives-inline-expectation

Required fixing up semantic conflicts in tests.

Conflicts:
	python/ql/test/experimental/library-tests/frameworks/stdlib/Decoding.py
This commit is contained in:
Jonas Jensen
2020-11-03 09:47:26 +01:00
180 changed files with 3494 additions and 3248 deletions

View File

@@ -1,4 +1,4 @@
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
/**
* A configuration to find all flows.

View File

@@ -1,4 +1,4 @@
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
where DataFlow::localFlow(fromNode, toNode)

View File

@@ -1,4 +1,4 @@
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
where DataFlow::localFlowStep(fromNode, toNode)

View File

@@ -1,5 +1,5 @@
import experimental.dataflow.DataFlow
private import experimental.dataflow.internal.DataFlowPrivate as DataFlowPrivate
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
/**
* A configuration to find all "maximal" flows.

View File

@@ -1,6 +1,6 @@
private import python
import experimental.dataflow.DataFlow
private import experimental.dataflow.internal.DataFlowPrivate as DataFlowPrivate
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
/**
* A configuration to find the call graph edges.

View File

@@ -1 +1 @@
import experimental.dataflow.internal.DataFlowImplConsistency::Consistency
import semmle.python.dataflow.new.internal.DataFlowImplConsistency::Consistency

View File

@@ -3,9 +3,9 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
private import experimental.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
/**
* A configuration to check routing of arguments through magic methods.

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -3,7 +3,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import DataFlow::PathGraph
/**

View File

@@ -1,5 +1,5 @@
import experimental.dataflow.DataFlow
private import experimental.dataflow.internal.DataFlowPrivate as DataFlowPrivate
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
/**
* A configuration to find the call graph edges.

View File

@@ -1,5 +1,5 @@
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
where

View File

@@ -1,5 +1,5 @@
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
where

View File

@@ -1,5 +1,5 @@
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
where

View File

@@ -1,5 +1,5 @@
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
class GlobalReadTest extends InlineExpectationsTest {

View File

@@ -1,4 +1,4 @@
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
query predicate importNode(DataFlow::Node res, string name) { res = DataFlow::importNode(name) }

View File

@@ -8,7 +8,7 @@
*/
import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
class CustomTestConfiguration extends DataFlow::Configuration {
CustomTestConfiguration() { this = "CustomTestConfiguration" }

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.DataFlow
private import experimental.dataflow.internal.DataFlowPrivate as DataFlowPrivate
import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
/** Gets the EssaNode that holds the module imported by the fully qualified module name `name` */
DataFlow::EssaNode module_import(string name) {

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.TaintTracking
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
where TaintTracking::localTaintStep(nodeFrom, nodeTo)

View File

@@ -16,12 +16,12 @@
| test_string.py:17 | ok | str_methods | ts.casefold() |
| test_string.py:19 | ok | str_methods | ts.format_map(..) |
| test_string.py:20 | ok | str_methods | "{unsafe}".format_map(..) |
| test_string.py:31 | fail | binary_decode_encode | base64.a85encode(..) |
| test_string.py:32 | fail | binary_decode_encode | base64.a85decode(..) |
| test_string.py:35 | fail | binary_decode_encode | base64.b85encode(..) |
| test_string.py:36 | fail | binary_decode_encode | base64.b85decode(..) |
| test_string.py:39 | fail | binary_decode_encode | base64.encodebytes(..) |
| test_string.py:40 | fail | binary_decode_encode | base64.decodebytes(..) |
| test_string.py:31 | ok | binary_decode_encode | base64.a85encode(..) |
| test_string.py:32 | ok | binary_decode_encode | base64.a85decode(..) |
| test_string.py:35 | ok | binary_decode_encode | base64.b85encode(..) |
| test_string.py:36 | ok | binary_decode_encode | base64.b85decode(..) |
| test_string.py:39 | ok | binary_decode_encode | base64.encodebytes(..) |
| test_string.py:40 | ok | binary_decode_encode | base64.decodebytes(..) |
| test_string.py:48 | ok | f_strings | Fstring |
| test_unpacking.py:18 | ok | extended_unpacking | first |
| test_unpacking.py:18 | ok | extended_unpacking | last |

View File

@@ -123,18 +123,18 @@
| test_string.py:114 | ok | percent_fmt | BinaryExpr |
| test_string.py:115 | ok | percent_fmt | BinaryExpr |
| test_string.py:116 | ok | percent_fmt | BinaryExpr |
| test_string.py:126 | fail | binary_decode_encode | base64.b64encode(..) |
| test_string.py:127 | fail | binary_decode_encode | base64.b64decode(..) |
| test_string.py:129 | fail | binary_decode_encode | base64.standard_b64encode(..) |
| test_string.py:130 | fail | binary_decode_encode | base64.standard_b64decode(..) |
| test_string.py:132 | fail | binary_decode_encode | base64.urlsafe_b64encode(..) |
| test_string.py:133 | fail | binary_decode_encode | base64.urlsafe_b64decode(..) |
| test_string.py:135 | fail | binary_decode_encode | base64.b32encode(..) |
| test_string.py:136 | fail | binary_decode_encode | base64.b32decode(..) |
| test_string.py:138 | fail | binary_decode_encode | base64.b16encode(..) |
| test_string.py:139 | fail | binary_decode_encode | base64.b16decode(..) |
| test_string.py:142 | fail | binary_decode_encode | base64.encodestring(..) |
| test_string.py:143 | fail | binary_decode_encode | base64.decodestring(..) |
| test_string.py:126 | ok | binary_decode_encode | base64.b64encode(..) |
| test_string.py:127 | ok | binary_decode_encode | base64.b64decode(..) |
| test_string.py:129 | ok | binary_decode_encode | base64.standard_b64encode(..) |
| test_string.py:130 | ok | binary_decode_encode | base64.standard_b64decode(..) |
| test_string.py:132 | ok | binary_decode_encode | base64.urlsafe_b64encode(..) |
| test_string.py:133 | ok | binary_decode_encode | base64.urlsafe_b64decode(..) |
| test_string.py:135 | ok | binary_decode_encode | base64.b32encode(..) |
| test_string.py:136 | ok | binary_decode_encode | base64.b32decode(..) |
| test_string.py:138 | ok | binary_decode_encode | base64.b16encode(..) |
| test_string.py:139 | ok | binary_decode_encode | base64.b16decode(..) |
| test_string.py:142 | ok | binary_decode_encode | base64.encodestring(..) |
| test_string.py:143 | ok | binary_decode_encode | base64.decodestring(..) |
| test_string.py:148 | fail | binary_decode_encode | quopri.encodestring(..) |
| test_string.py:149 | fail | binary_decode_encode | quopri.decodestring(..) |
| test_string.py:159 | ok | test_os_path_join | os.path.join(..) |

View File

@@ -21,7 +21,7 @@
*/
private import python
import experimental.dataflow.DataFlow
import semmle.python.dataflow.new.DataFlow
class TestConfiguration extends DataFlow::Configuration {
TestConfiguration() { this = "TestConfiguration" }

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.DataFlow
import experimental.dataflow.TypeTracker
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TypeTracker
DataFlow::Node module_tracker(TypeTracker t) {
t.start() and

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.DataFlow
import experimental.dataflow.TypeTracker
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TypeTracker
import TestUtilities.InlineExpectationsTest
DataFlow::Node tracked(TypeTracker t) {

View File

@@ -1,5 +1,5 @@
import experimental.dataflow.tainttracking.TestTaintLib
import experimental.dataflow.RemoteFlowSources
import semmle.python.dataflow.new.RemoteFlowSources
class RemoteFlowTestTaintConfiguration extends TestTaintTrackingConfiguration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -78,7 +78,7 @@ urlpatterns = [
def page_number(request, page_number=1): # $routeHandler routedParameter=page_number
return HttpResponse('page_number: {}'.format(page_number)) # $HttpResponse
def foo_bar_baz(request, foo, bar, baz): # $routeHandler $routedParameter=foo routedParameter=bar routedParameter=baz
def foo_bar_baz(request, foo, bar, baz): # $routeHandler routedParameter=foo routedParameter=bar routedParameter=baz
return HttpResponse('foo_bar_baz: {} {} {}'.format(foo, bar, baz)) # $HttpResponse
def path_kwargs(request, foo, bar): # $routeHandler routedParameter=foo routedParameter=bar

View File

@@ -20,7 +20,7 @@ class User(models.Model):
def test_model():
User.objects.raw("some sql") # $getSql="some sql"
User.objects.annotate(RawSQL("some sql")) # $getSql="some sql"
User.objects.annotate(RawSQL("foo"), RawSQL("bar")) # $getSql="foo" $getSql="bar"
User.objects.annotate(RawSQL("foo"), RawSQL("bar")) # $getSql="foo" getSql="bar"
User.objects.annotate(val=RawSQL("some sql")) # $getSql="some sql"
User.objects.extra("some sql") # $getSql="some sql"
User.objects.extra(select="select", where="where", tables="tables", order_by="order_by") # $getSql="select" getSql="where" getSql="tables" getSql="order_by"

View File

@@ -1,5 +1,5 @@
import experimental.dataflow.tainttracking.TestTaintLib
import experimental.dataflow.RemoteFlowSources
import semmle.python.dataflow.new.RemoteFlowSources
class RemoteFlowTestTaintConfiguration extends TestTaintTrackingConfiguration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -3,8 +3,8 @@
*/
private import python
private import experimental.dataflow.DataFlow
private import experimental.dataflow.TaintTracking
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
import DataFlow::PathGraph
import SharedCode

View File

@@ -3,8 +3,8 @@
*/
private import python
private import experimental.dataflow.DataFlow
private import experimental.dataflow.TaintTracking
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
import DataFlow::PathGraph
import SharedCode

View File

@@ -1,6 +1,6 @@
private import python
private import experimental.dataflow.DataFlow
private import experimental.dataflow.TaintTracking
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.TaintTracking
// Helpers modeling MyClass
/** A data-flow Node representing an instance of MyClass. */

View File

@@ -0,0 +1,2 @@
import python
import experimental.meta.ConceptsTest

View File

@@ -0,0 +1,37 @@
# taken from https://dev.mysql.com/doc/connector-python/en/connector-python-example-cursor-transaction.html
from __future__ import print_function
from datetime import date, datetime, timedelta
import mysql.connector
cnx = mysql.connector.connect(user='scott', database='employees')
cursor = cnx.cursor()
tomorrow = datetime.now().date() + timedelta(days=1)
add_employee = ("INSERT INTO employees "
"(first_name, last_name, hire_date, gender, birth_date) "
"VALUES (%s, %s, %s, %s, %s)")
add_salary = ("INSERT INTO salaries "
"(emp_no, salary, from_date, to_date) "
"VALUES (%(emp_no)s, %(salary)s, %(from_date)s, %(to_date)s)")
data_employee = ('Geert', 'Vanderkelen', tomorrow, 'M', date(1977, 6, 14))
# Insert new employee
cursor.execute(add_employee, data_employee) # $getSql=add_employee
emp_no = cursor.lastrowid
# Insert salary information
data_salary = {
'emp_no': emp_no,
'salary': 50000,
'from_date': tomorrow,
'to_date': date(9999, 1, 1),
}
cursor.execute(add_salary, data_salary) # $getSql=add_salary
# Make sure data is committed to the database
cnx.commit()
cursor.close()
cnx.close()

View File

@@ -0,0 +1,2 @@
import python
import experimental.meta.ConceptsTest

View File

@@ -0,0 +1,7 @@
# taken from https://mysqlclient.readthedocs.io/user_guide.html#some-examples
import MySQLdb
db=MySQLdb.connect(passwd="moonpie",db="thangs")
c=db.cursor()
max_price=5
c.execute("some sql", (max_price,)) # $getSql="some sql"

View File

@@ -0,0 +1,6 @@
import base64
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py
base64.a85decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Ascii85
base64.b85decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base85
base64.decodebytes(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64

View File

@@ -0,0 +1,6 @@
import base64
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep-py3/test_string.py
base64.a85encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Ascii85
base64.b85encode(bs)# $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base85
base64.encodebytes(bs)# $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64

View File

@@ -1,5 +1,15 @@
import pickle
import marshal
import base64
pickle.loads(payload) # $decodeInput=payload decodeOutput=Attribute() decodeFormat=pickle decodeMayExecuteInput
marshal.loads(payload) # $decodeInput=payload decodeOutput=Attribute() decodeFormat=marshal decodeMayExecuteInput
pickle.loads(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=pickle decodeMayExecuteInput
marshal.loads(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=marshal decodeMayExecuteInput
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py
base64.b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
base64.standard_b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
base64.urlsafe_b64decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64
base64.b32decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base32
base64.b16decode(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base16
# deprecated since Python 3.1, but still works
base64.decodestring(payload) # $ decodeInput=payload decodeOutput=Attribute() decodeFormat=Base64

View File

@@ -0,0 +1,15 @@
import pickle
import marshal
import base64
pickle.dumps(obj) # $ MISSING: f-:encodeInput=obj f-:encodeOutput=Attribute() f-:encodeFormat=pickle f-:encodeMayExecuteInput
marshal.dumps(obj) # $ MISSING: f-:encodeInput=obj f-:encodeOutput=Attribute() f-:encodeFormat=marshal f-:encodeMayExecuteInput
# TODO: These tests should be merged with python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_string.py
base64.b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
base64.standard_b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
base64.urlsafe_b64encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64
base64.b32encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base32
base64.b16encode(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base16
# deprecated since Python 3.1, but still works
base64.encodestring(bs) # $ encodeInput=bs encodeOutput=Attribute() encodeFormat=Base64

View File

@@ -1,2 +1,2 @@
import experimental.dataflow.tainttracking.TestTaintLib
import experimental.dataflow.RemoteFlowSources
import semmle.python.dataflow.new.RemoteFlowSources

View File

@@ -1,6 +1,6 @@
import python
import experimental.dataflow.DataFlow
import experimental.semmle.python.Concepts
import semmle.python.dataflow.new.DataFlow
import semmle.python.Concepts
import TestUtilities.InlineExpectationsTest
string value_from_expr(Expr e) {
@@ -73,6 +73,38 @@ class DecodingTest extends InlineExpectationsTest {
}
}
class EncodingTest extends InlineExpectationsTest {
EncodingTest() { this = "EncodingTest" }
override string getARelevantTag() { result in ["encodeInput", "encodeOutput", "encodeFormat"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(Encoding e |
exists(DataFlow::Node data |
location = data.getLocation() and
element = data.toString() and
value = value_from_expr(data.asExpr()) and
(
data = e.getAnInput() and
tag = "encodeInput"
or
data = e.getOutput() and
tag = "encodeOutput"
)
)
or
exists(string format |
location = e.getLocation() and
element = format and
value = format and
format = e.getFormat() and
tag = "encodeFormat"
)
)
}
}
class CodeExecutionTest extends InlineExpectationsTest {
CodeExecutionTest() { this = "CodeExecutionTest" }

View File

@@ -1,94 +0,0 @@
edges
| path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() |
| path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() |
| path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() | path_injection.py:17:14:17:18 | ControlFlowNode for npath |
| path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() |
| path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() | path_injection.py:28:14:28:18 | ControlFlowNode for npath |
| path_injection.py:33:12:33:23 | ControlFlowNode for Attribute | path_injection.py:34:13:34:61 | ControlFlowNode for Attribute() |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:18:9:18:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:24:9:24:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:31:9:31:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:38:9:38:16 | ControlFlowNode for source() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:46:9:46:16 | ControlFlowNode for source() |
| test.py:12:15:12:15 | SSA variable x | test.py:13:12:13:30 | ControlFlowNode for Attribute() |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() |
| test.py:18:9:18:16 | ControlFlowNode for source() | test.py:19:10:19:10 | ControlFlowNode for x |
| test.py:24:9:24:16 | ControlFlowNode for source() | test.py:25:19:25:19 | ControlFlowNode for x |
| test.py:25:9:25:20 | ControlFlowNode for normalize() | test.py:26:10:26:10 | ControlFlowNode for y |
| test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | SSA variable x |
| test.py:31:9:31:16 | ControlFlowNode for source() | test.py:33:14:33:14 | ControlFlowNode for x |
| test.py:38:9:38:16 | ControlFlowNode for source() | test.py:39:19:39:19 | ControlFlowNode for x |
| test.py:39:19:39:19 | ControlFlowNode for x | test.py:12:15:12:15 | SSA variable x |
| test.py:46:9:46:16 | ControlFlowNode for source() | test.py:48:23:48:23 | ControlFlowNode for x |
| test.py:48:13:48:24 | ControlFlowNode for normalize() | test.py:49:14:49:14 | ControlFlowNode for y |
| test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | SSA variable x |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:20:9:20:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:28:9:28:16 | ControlFlowNode for source() |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | test_chaining.py:41:9:41:16 | ControlFlowNode for source() |
| test_chaining.py:14:15:14:15 | SSA variable x | test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() |
| test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() | test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() |
| test_chaining.py:20:9:20:16 | ControlFlowNode for source() | test_chaining.py:21:19:21:19 | ControlFlowNode for x |
| test_chaining.py:21:19:21:19 | ControlFlowNode for x | test_chaining.py:14:15:14:15 | SSA variable x |
| test_chaining.py:28:9:28:16 | ControlFlowNode for source() | test_chaining.py:29:19:29:19 | ControlFlowNode for x |
| test_chaining.py:29:19:29:19 | ControlFlowNode for x | test_chaining.py:14:15:14:15 | SSA variable x |
| test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() | test_chaining.py:32:14:32:14 | ControlFlowNode for z |
| test_chaining.py:41:9:41:16 | ControlFlowNode for source() | test_chaining.py:42:9:42:19 | ControlFlowNode for normpath() |
| test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | test_chaining.py:45:14:45:14 | ControlFlowNode for z |
nodes
| path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:16:13:16:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:17:14:17:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:25:13:25:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| path_injection.py:28:14:28:18 | ControlFlowNode for npath | semmle.label | ControlFlowNode for npath |
| path_injection.py:33:12:33:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| path_injection.py:34:13:34:61 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:12:15:12:15 | SSA variable x | semmle.label | SSA variable x |
| test.py:13:12:13:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test.py:18:9:18:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:19:10:19:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:24:9:24:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:25:9:25:20 | ControlFlowNode for normalize() | semmle.label | ControlFlowNode for normalize() |
| test.py:25:19:25:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:26:10:26:10 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test.py:31:9:31:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:33:14:33:14 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:38:9:38:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:39:19:39:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:46:9:46:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test.py:48:13:48:24 | ControlFlowNode for normalize() | semmle.label | ControlFlowNode for normalize() |
| test.py:48:23:48:23 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test.py:49:14:49:14 | ControlFlowNode for y | semmle.label | ControlFlowNode for y |
| test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test_chaining.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test_chaining.py:14:15:14:15 | SSA variable x | semmle.label | SSA variable x |
| test_chaining.py:15:12:15:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| test_chaining.py:20:9:20:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:21:19:21:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:28:9:28:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:29:19:29:19 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
| test_chaining.py:31:13:31:24 | ControlFlowNode for normalize() | semmle.label | ControlFlowNode for normalize() |
| test_chaining.py:32:14:32:14 | ControlFlowNode for z | semmle.label | ControlFlowNode for z |
| test_chaining.py:41:9:41:16 | ControlFlowNode for source() | semmle.label | ControlFlowNode for source() |
| test_chaining.py:42:9:42:19 | ControlFlowNode for normpath() | semmle.label | ControlFlowNode for normpath() |
| test_chaining.py:44:13:44:23 | ControlFlowNode for normpath() | semmle.label | ControlFlowNode for normpath() |
| test_chaining.py:45:14:45:14 | ControlFlowNode for z | semmle.label | ControlFlowNode for z |
#select
| path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | path_injection.py:10:14:10:44 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |
| path_injection.py:17:14:17:18 | ControlFlowNode for npath | path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | path_injection.py:17:14:17:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:15:12:15:23 | ControlFlowNode for Attribute | a user-provided value |
| path_injection.py:28:14:28:18 | ControlFlowNode for npath | path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | path_injection.py:28:14:28:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:24:12:24:23 | ControlFlowNode for Attribute | a user-provided value |
| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |
| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |
| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |
| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |
| test_chaining.py:32:14:32:14 | ControlFlowNode for z | test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | test_chaining.py:32:14:32:14 | ControlFlowNode for z | This path depends on $@. | test_chaining.py:9:12:9:23 | ControlFlowNode for Attribute | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-022/PathInjection.ql

View File

@@ -1,36 +0,0 @@
import os.path
from flask import Flask, request
app = Flask(__name__)
@app.route("/path1")
def path_injection():
path = request.args.get('path', '')
f = open(os.path.join(os.getcwd(), path))
@app.route("/path2")
def path_injection():
# Normalized, but not checked
path = request.args.get('path', '')
npath = os.path.normpath(os.path.join(os.getcwd(), path))
f = open(npath) # Path not found
SAFE = "/tmp/scratch_area/"
@app.route("/path3")
def safe_path():
# Normalized, but check doesn't reach open().
path = request.args.get('path', '')
npath = os.path.normpath(os.path.join(os.getcwd(), path))
if npath.startswith(SAFE):
pass
f = open(npath) # Path not found
@app.route("/path4")
def safe_path():
# Normalized, and checked properly
path = request.args.get('path', '')
npath = os.path.normpath(os.path.join(os.getcwd(), path))
if npath.startswith(SAFE):
f = open(npath)

View File

@@ -1,49 +0,0 @@
import os.path
from flask import Flask, request
app = Flask(__name__)
def source():
return request.args.get("path", "")
def normalize(x):
return os.path.normpath(x)
@app.route("/path")
def simple():
x = source()
open(x) # NOT OK
@app.route("/path")
def normalization():
x = source()
y = normalize(x)
open(y) # NOT OK
@app.route("/path")
def check():
x = source()
if x.startswith("subfolder/"):
open(x) # NOT OK
@app.route("/path")
def normalize_then_check():
x = source()
y = normalize(x)
if y.startswith("subfolder/"):
open(y) # OK
@app.route("/path")
def check_then_normalize():
x = source()
if x.startswith("subfolder/"):
y = normalize(x)
open(y) # NOT OK

View File

@@ -1,45 +0,0 @@
import os.path
from flask import Flask, request
app = Flask(__name__)
def source():
return request.args.get("path", "")
# Wrap normalization, so we can fool the chained configurations.
# (Call context is lost at cross-over nodes.)
def normalize(x):
return os.path.normpath(x)
@app.route("/path")
def normalize_then_check():
x = source()
y = normalize(x) # <--- this call...
if y.startswith("subfolder/"):
open(y) # OK
@app.route("/path")
def normalize_check_normalize():
x = source()
y = normalize(x) # (...or this call...)
if y.startswith("subfolder/"):
z = normalize(y) # <--- ...can jump to here, resulting in FP
open(z) # OK
# The problem does not manifest if we simply define an alias
normpath = os.path.normpath
@app.route("/path")
def normalize_check_normalize_alias():
x = source()
y = normpath(x)
if y.startswith("subfolder/"):
z = normpath(y)
open(z) # OK

View File

@@ -1,31 +0,0 @@
edges
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr |
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr |
nodes
| command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
#select
| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-078/CommandInjection.ql

View File

@@ -1,29 +0,0 @@
import os
import platform
import popen2
from flask import Flask, request
app = Flask(__name__)
@app.route("/python2-specific")
def python2_specific():
"""
These tests are mostly included to check for extra paths that can be generated if
we can track flow into the implementation of a stdlib function, and then to another sink.
See comment in query for more details.
"""
files = request.args.get("files", "")
os.popen2("ls " + files)
os.popen3("ls " + files)
os.popen4("ls " + files)
platform.popen("ls " + files)
popen2.popen2("ls " + files)
popen2.popen3("ls " + files)
popen2.popen4("ls " + files)
popen2.Popen3("ls " + files)
popen2.Popen4("ls " + files)

View File

@@ -1 +0,0 @@
semmle-extractor-options: --max-import-depth=1 --lang=2

View File

@@ -1,42 +0,0 @@
edges
| command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr |
| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr |
| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd |
| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr |
| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command |
| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command |
nodes
| command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
| command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:39:15:39:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:40:15:40:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| command_injection.py:53:15:53:21 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:54:14:54:20 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:55:21:55:27 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:56:27:56:33 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
| command_injection.py:57:20:57:26 | ControlFlowNode for command | semmle.label | ControlFlowNode for command |
#select
| command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | command_injection.py:12:15:12:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:10:13:10:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | command_injection.py:19:22:19:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:17:13:17:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:25:23:25:25 | ControlFlowNode for cmd | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | command_injection.py:25:23:25:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:24:11:24:22 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | command_injection.py:32:14:32:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:30:13:30:24 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:39:15:39:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:39:15:39:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:40:15:40:21 | ControlFlowNode for command | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | command_injection.py:40:15:40:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:36:15:36:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:53:15:53:21 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:53:15:53:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:54:14:54:20 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:54:14:54:20 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:55:21:55:27 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:55:21:55:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:56:27:56:33 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:56:27:56:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value |
| command_injection.py:57:20:57:26 | ControlFlowNode for command | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | command_injection.py:57:20:57:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:52:15:52:26 | ControlFlowNode for Attribute | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-078/CommandInjection.ql

View File

@@ -1,57 +0,0 @@
import os
import subprocess
from flask import Flask, request
app = Flask(__name__)
@app.route("/command1")
def command_injection1():
files = request.args.get('files', '')
# Don't let files be `; rm -rf /`
os.system("ls " + files)
@app.route("/command2")
def command_injection2():
files = request.args.get('files', '')
# Don't let files be `; rm -rf /`
subprocess.Popen("ls " + files, shell=True)
@app.route("/command3")
def first_arg_injection():
cmd = request.args.get('cmd', '')
subprocess.Popen([cmd, "param1"])
@app.route("/other_cases")
def others():
files = request.args.get('files', '')
# Don't let files be `; rm -rf /`
os.popen("ls " + files)
@app.route("/multiple")
def multiple():
command = request.args.get('command', '')
# We should mark flow to both calls here, which conflicts with removing flow out of
# a sink due to use-use flow.
os.system(command)
os.system(command)
@app.route("/not-into-sink-impl")
def not_into_sink_impl():
"""When there is flow to a sink such as `os.popen(cmd)`, we don't want to highlight that there is also
flow through the actual `popen` function to the internal call to `subprocess.Popen` -- we would usually
see that flow since we extract the `os.py` file from the standard library.
os.popen implementation: https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/os.py#L974
subprocess.call implementation: https://github.com/python/cpython/blob/fa7ce080175f65d678a7d5756c94f82887fc9803/Lib/subprocess.py#L341
"""
command = request.args.get('command', '')
os.system(command)
os.popen(command)
subprocess.call(command)
subprocess.check_call(command)
subprocess.run(command)

View File

@@ -1,7 +0,0 @@
edges
| reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr |
nodes
| reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
#select
| reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | reflected_xss.py:9:26:9:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:8:18:8:29 | ControlFlowNode for Attribute | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-079/ReflectedXss.ql

View File

@@ -1,15 +0,0 @@
from flask import Flask, request, make_response, escape
app = Flask(__name__)
@app.route("/unsafe")
def unsafe():
first_name = request.args.get("name", "")
return make_response("Your name is " + first_name) # NOT OK
@app.route("/safe")
def safe():
first_name = request.args.get("name", "")
return make_response("Your name is " + escape(first_name)) # OK

View File

@@ -1,16 +0,0 @@
edges
| sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr |
| sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr |
| sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr |
| sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr |
nodes
| sql_injection.py:14:15:14:22 | SSA variable username | semmle.label | SSA variable username |
| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr |
#select
| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | SSA variable username | a user-provided value |
| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | SSA variable username | a user-provided value |
| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | SSA variable username | a user-provided value |
| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | SSA variable username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | SSA variable username | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-089/SqlInjection.ql

View File

@@ -1,40 +0,0 @@
"""This is adapted from ql/python/ql/test/query-tests\Security\CWE-089
we now prefer to setup routing by flask
"""
from django.db import connection, models
from django.db.models.expressions import RawSQL
from flask import Flask, request
app = Flask(__name__)
class User(models.Model):
pass
@app.route("/users/<username>")
def show_user(username):
with connection.cursor() as cursor:
# GOOD -- Using parameters
cursor.execute("SELECT * FROM users WHERE username = %s", username)
User.objects.raw("SELECT * FROM users WHERE username = %s", (username,))
# BAD -- Using string formatting
cursor.execute("SELECT * FROM users WHERE username = '%s'" % username)
# BAD -- other ways of executing raw SQL code with string interpolation
User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username))
User.objects.raw("insert into names_file ('name') values ('%s')" % username)
User.objects.extra("insert into names_file ('name') values ('%s')" % username)
# BAD (but currently no custom query to find this)
#
# It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra)
# For example, using name = "; DROP ALL TABLES -- "
# will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- ''
#
# This shouldn't be very widespread, since using a normal string will result in invalid SQL
# Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example''
# which in MySQL will give a syntax error
#
# When testing this out locally, none of the queries worked against SQLite3, but I could use
# the SQL injection against MySQL.
User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,))

View File

@@ -1,13 +0,0 @@
edges
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:7:10:7:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:8:10:8:13 | ControlFlowNode for code |
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:10:10:10:12 | ControlFlowNode for cmd |
nodes
| code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| code_injection.py:7:10:7:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code |
| code_injection.py:8:10:8:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code |
| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | semmle.label | ControlFlowNode for cmd |
#select
| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:7:10:7:13 | ControlFlowNode for code | $@ flows to here and is interpreted as code. | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | A user-provided value |
| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:8:10:8:13 | ControlFlowNode for code | $@ flows to here and is interpreted as code. | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | A user-provided value |
| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | $@ flows to here and is interpreted as code. | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | A user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-094/CodeInjection.ql

View File

@@ -1,10 +0,0 @@
from flask import Flask, request
app = Flask(__name__)
@app.route("/code-execution")
def code_execution():
code = request.args.get("code")
exec(code)
eval(code)
cmd = compile(code, "<filename>", "exec")
exec(cmd)

View File

@@ -1,16 +0,0 @@
edges
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload |
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload |
nodes
| unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload |
#select
| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |
| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | untrusted input |

View File

@@ -1 +0,0 @@
experimental/Security-new-dataflow/CWE-502/UnsafeDeserialization.ql

View File

@@ -1,21 +0,0 @@
import flask
import pickle
import yaml
import marshal
from yaml import SafeLoader
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def hello():
payload = request.args.get("payload")
pickle.loads(payload) # NOT OK
yaml.load(payload) # NOT OK
yaml.load(payload, Loader=SafeLoader) # OK
marshal.loads(payload) # NOT OK
import dill
dill.loads(payload) # NOT OK