python.flask.security.injection.os-system-injection.os-system-injection
Verifed by r2c
Community Favorite
semgrep
Author
129,896
Download Count*
License
User data detected in os.system. This could be vulnerable to a command injection and should be avoided. If this must be done, use the 'subprocess' module instead and pass the arguments as a list.
Run Locally
Run in CI
Defintion
rules:
- id: os-system-injection
languages:
- python
severity: ERROR
message: User data detected in os.system. This could be vulnerable to a command
injection and should be avoided. If this must be done, use the
'subprocess' module instead and pass the arguments as a list.
metadata:
cwe:
- "CWE-78: Improper Neutralization of Special Elements used in an OS
Command ('OS Command Injection')"
owasp:
- A01:2017 - Injection
- A03:2021 - Injection
references:
- https://owasp.org/www-community/attacks/Command_Injection
category: security
technology:
- flask
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: MEDIUM
impact: HIGH
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Command Injection
pattern-either:
- patterns:
- pattern: os.system(...)
- pattern-either:
- pattern-inside: |
@$APP.route($ROUTE, ...)
def $FUNC(..., $ROUTEVAR, ...):
...
os.system(..., <... $ROUTEVAR ...>, ...)
- pattern-inside: |
@$APP.route($ROUTE, ...)
def $FUNC(..., $ROUTEVAR, ...):
...
$INTERM = <... $ROUTEVAR ...>
...
os.system(..., <... $INTERM ...>, ...)
- pattern: os.system(..., <... flask.request.$W.get(...) ...>, ...)
- pattern: os.system(..., <... flask.request.$W[...] ...>, ...)
- pattern: os.system(..., <... flask.request.$W(...) ...>, ...)
- pattern: os.system(..., <... flask.request.$W ...>, ...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W.get(...) ...>
...
os.system(<... $INTERM ...>)
- pattern: os.system(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W[...] ...>
...
os.system(<... $INTERM ...>)
- pattern: os.system(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W(...) ...>
...
os.system(<... $INTERM ...>)
- pattern: os.system(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W ...>
...
os.system(<... $INTERM ...>)
- pattern: os.system(...)
Examples
os-system-injection.py
import os
import flask
import hashlib
app = flask.Flask(__name__)
@app.route("/route_param/<route_param>")
def route_param(route_param):
print("blah")
# ruleid: os-system-injection
return os.system(route_param)
@app.route("/route_param_ok/<route_param>")
def route_param_ok(route_param):
print("blah")
# ok: os-system-injection
return os.system("ls -la")
@app.route("/route_param_concat/<route_param>")
def route_param_concat(route_param):
print("blah")
# ruleid: os-system-injection
return os.system("echo " + route_param)
@app.route("/route_param_format/<route_param>")
def route_param_format(route_param):
print("blah")
# ruleid: os-system-injection
return os.system("echo {}".format(route_param))
@app.route("/route_param_percent_format/<route_param>")
def route_param_percent_format(route_param):
print("blah")
# ruleid: os-system-injection
return os.system("echo %s" % route_param)
@app.route("/get_param_inline", methods=["GET"])
def get_param_inline():
# ruleid: os-system-injection
os.system(flask.request.args.get("param"))
@app.route("/get_param_inline_concat", methods=["GET"])
def get_param_inline_concat():
# ruleid: os-system-injection
os.system("echo " + flask.request.args.get("param"))
@app.route("/get_param", methods=["GET"])
def get_param():
param = flask.request.args.get("param")
# ruleid: os-system-injection
os.system(param)
@app.route("/get_param_concat", methods=["GET"])
def get_param_concat():
param = flask.request.args.get("param")
# ruleid: os-system-injection
os.system("echo " + param)
@app.route("/get_param_format", methods=["GET"])
def get_param_format():
param = flask.request.args.get("param")
# ruleid: os-system-injection
os.system("echo {}".format(param))
@app.route("/get_param_percent_format", methods=["GET"])
def get_param_percent_format():
param = flask.request.args.get("param")
# ruleid: os-system-injection
os.system("echo %s" % (param,))
@app.route("/post_param", methods=["POST"])
def post_param():
param = flask.request.form['param']
# ruleid: os-system-injection
os.system(param)
@app.route("/post_param_branch", methods=["POST"])
def post_param_branch():
param = flask.request.form['param']
if True:
# ruleid: os-system-injection
os.system(param)
@app.route("/subexpression", methods=["POST"])
def subexpression():
param = "{}".format(flask.request.form['param'])
print("do things")
# ruleid: os-system-injection
os.system(param)
@app.route("/subexpression_concat", methods=["POST"])
def subexpression_concat():
param = "{}".format(flask.request.form['param'])
print("do things")
# ruleid: os-system-injection
os.system("echo " + param)
@app.route("/subexpression_format", methods=["POST"])
def subexpression_format():
param = "{}".format(flask.request.form['param'])
print("do things")
# ruleid: os-system-injection
os.system("echo {}".format(param))
@app.route("/subexpression_percent_format", methods=["POST"])
def subexpression_percent_format():
param = "{}".format(flask.request.form['param'])
print("do things")
# ruleid: os-system-injection
os.system("echo %s" % param)
# Real world example
@app.route('/', methods=['GET', 'POST'])
def index():
if flask.request.method == 'GET':
return flask.render_template('index.html')
# check url first
url = flask.request.form.get('url', None)
if url != '':
md5 = hashlib.md5(url+app.config['MD5_SALT']).hexdigest()
fpath = join(join(app.config['MEDIA_ROOT'], 'upload'), md5+'.jpg')
# ruleid: os-system-injection
r = os.system('wget %s -O "%s"'%(url, fpath))
if r != 0: abort(403)
return flask.redirect(flask.url_for('landmark', hash=md5))
@app.route("/ok")
def ok():
# ok: os-system-injection
os.system("This is fine")
Short Link: https://sg.run/4xzz