diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.expected new file mode 100644 index 00000000000..3875da4e143 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.expected @@ -0,0 +1,2 @@ +missingAnnotationOnSink +failures diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql new file mode 100644 index 00000000000..c69cc5c7578 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/DataflowQueryTest.ql @@ -0,0 +1,3 @@ +import python +import experimental.dataflow.TestUtil.DataflowQueryTest +import semmle.python.security.dataflow.CommandInjectionQuery diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py index 978a2bf986c..ef8cb221ea0 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/command_injection.py @@ -10,27 +10,27 @@ app = Flask(__name__) def command_injection1(): files = request.args.get('files', '') # Don't let files be `; rm -rf /` - os.system("ls " + files) + os.system("ls " + files) # $flow="ImportMember, l:-8 -> BinaryExpr" @app.route("/command2") def command_injection2(): files = request.args.get('files', '') # Don't let files be `; rm -rf /` - subprocess.Popen("ls " + files, shell=True) + subprocess.Popen("ls " + files, shell=True) # $flow="ImportMember, l:-15 -> BinaryExpr" @app.route("/command3") def first_arg_injection(): cmd = request.args.get('cmd', '') - subprocess.Popen([cmd, "param1"]) + subprocess.Popen([cmd, "param1"]) # $flow="ImportMember, l:-21 -> cmd" @app.route("/other_cases") def others(): files = request.args.get('files', '') # Don't let files be `; rm -rf /` - os.popen("ls " + files) + os.popen("ls " + files) # $flow="ImportMember, l:-28 -> BinaryExpr" @app.route("/multiple") @@ -38,8 +38,8 @@ 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) + os.system(command) # $flow="ImportMember, l:-36 -> command" + os.system(command) # $flow="ImportMember, l:-37 -> command" @app.route("/not-into-sink-impl") @@ -52,11 +52,11 @@ def not_into_sink_impl(): 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) + os.system(command) # $flow="ImportMember, l:-50 -> command" + os.popen(command) # $flow="ImportMember, l:-51 -> command" + subprocess.call(command) # $flow="ImportMember, l:-52 -> command" + subprocess.check_call(command) # $flow="ImportMember, l:-53 -> command" + subprocess.run(command) # $flow="ImportMember, l:-54 -> command" @app.route("/path-exists-not-sanitizer") @@ -70,11 +70,11 @@ def path_exists_not_sanitizer(): """ path = request.args.get('path', '') if os.path.exists(path): - os.system("ls " + path) # NOT OK + os.system("ls " + path) # $flow="ImportMember, l:-68 -> BinaryExpr" @app.route("/restricted-characters") def restricted_characters(): path = request.args.get('path', '') if re.match(r'^[a-zA-Z0-9_-]+$', path): - os.system("ls " + path) # OK (TODO: Currently FP) + os.system("ls " + path) # $SPURIOUS: flow="ImportMember, l:-75 -> BinaryExpr"