python: inline query tests for command injection

note how the test file is partially annotated
and those annotations can now be expressed

In this particular test file, absolute line numbers
might have been better than relative ones.
We might remove line numbers altogether,
but should check more querries to see how it looks.
This commit is contained in:
Rasmus Lerchedahl Petersen
2022-11-02 16:21:59 +01:00
parent f486c44b00
commit 0a7cfad048
3 changed files with 18 additions and 13 deletions

View File

@@ -0,0 +1,2 @@
missingAnnotationOnSink
failures

View File

@@ -0,0 +1,3 @@
import python
import experimental.dataflow.TestUtil.DataflowQueryTest
import semmle.python.security.dataflow.CommandInjectionQuery

View File

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