python.flask.security.injection.path-traversal-open.path-traversal-open
Verifed by r2c
Community Favorite
semgrep
Author
129,048
Download Count*
License
Found request data in a call to 'open'. Ensure the request data is validated or sanitized, otherwise it could result in path traversal attacks.
Run Locally
Run in CI
Defintion
rules:
- id: path-traversal-open
languages:
- python
severity: ERROR
message: Found request data in a call to 'open'. Ensure the request data is
validated or sanitized, otherwise it could result in path traversal
attacks.
metadata:
cwe:
- "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
('Path Traversal')"
owasp:
- A05:2017 - Broken Access Control
- A01:2021 - Broken Access Control
references:
- https://owasp.org/www-community/attacks/Path_Traversal
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:
- Path Traversal
pattern-either:
- patterns:
- pattern: open(...)
- pattern-either:
- pattern-inside: |
@$APP.route($ROUTE, ...)
def $FUNC(..., $ROUTEVAR, ...):
...
open(..., <... $ROUTEVAR ...>, ...)
- pattern-inside: |
@$APP.route($ROUTE, ...)
def $FUNC(..., $ROUTEVAR, ...):
...
with open(..., <... $ROUTEVAR ...>, ...) as $FD:
...
- pattern-inside: |
@$APP.route($ROUTE, ...)
def $FUNC(..., $ROUTEVAR, ...):
...
$INTERM = <... $ROUTEVAR ...>
...
open(..., <... $INTERM ...>, ...)
- pattern: open(..., <... flask.request.$W.get(...) ...>, ...)
- pattern: open(..., <... flask.request.$W[...] ...>, ...)
- pattern: open(..., <... flask.request.$W(...) ...>, ...)
- pattern: open(..., <... flask.request.$W ...>, ...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W.get(...) ...>
...
open(<... $INTERM ...>, ...)
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W[...] ...>
...
open(<... $INTERM ...>, ...)
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W(...) ...>
...
open(<... $INTERM ...>, ...)
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W ...>
...
open(<... $INTERM ...>, ...)
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W.get(...) ...>
...
with open(<... $INTERM ...>, ...) as $F:
...
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W[...] ...>
...
with open(<... $INTERM ...>, ...) as $F:
...
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W(...) ...>
...
with open(<... $INTERM ...>, ...) as $F:
...
- pattern: open(...)
- patterns:
- pattern-inside: |
$INTERM = <... flask.request.$W ...>
...
with open(<... $INTERM ...>, ...) as $F:
...
- pattern: open(...)
Examples
path-traversal-open.py
import flask
import json
app = flask.Flask(__name__)
@app.route("/route_param/<route_param>")
def route_param(route_param):
print("blah")
# ruleid: path-traversal-open
return open(route_param, 'r').read()
@app.route("/route_param_ok/<route_param>")
def route_param_ok(route_param):
print("blah")
# ok: path-traversal-open
return open("this is safe", 'r').read()
@app.route("/route_param_with/<route_param>")
def route_param_with(route_param):
print("blah")
# ruleid: path-traversal-open
with open(route_param, 'r') as fout:
return fout.read()
@app.route("/route_param_with_ok/<route_param>")
def route_param_with_ok(route_param):
print("blah")
# ok: path-traversal-open
with open("this is safe", 'r') as fout:
return fout.read()
@app.route("/route_param_with_concat/<route_param>")
def route_param_with_concat(route_param):
print("blah")
# ruleid: path-traversal-open
with open(route_param + ".csv", 'r') as fout:
return fout.read()
@app.route("/get_param", methods=["GET"])
def get_param():
param = flask.request.args.get("param")
# ruleid: path-traversal-open
f = open(param, 'w')
f.write("hello world")
@app.route("/get_param_inline_concat", methods=["GET"])
def get_param_inline_concat():
# ruleid: path-traversal-open
return open("echo " + flask.request.args.get("param"), 'r').read()
@app.route("/get_param_concat", methods=["GET"])
def get_param_concat():
param = flask.request.args.get("param")
# ruleid: path-traversal-open
return open(param + ".csv", 'r').read()
@app.route("/get_param_format", methods=["GET"])
def get_param_format():
param = flask.request.args.get("param")
# ruleid: path-traversal-open
return open("{}.csv".format(param)).read()
@app.route("/get_param_percent_format", methods=["GET"])
def get_param_percent_format():
param = flask.request.args.get("param")
# ruleid: path-traversal-open
return open("echo %s" % (param,), 'r').read()
@app.route("/post_param", methods=["POST"])
def post_param():
param = flask.request.form['param']
if True:
# ruleid: path-traversal-open
with open(param, 'r') as fin:
data = json.load(fin)
return data
@app.route("/post_param", methods=["POST"])
def post_param_with_inline():
# ruleid: path-traversal-open
with open(flask.request.form['param'], 'r') as fin:
data = json.load(fin)
return data
@app.route("/post_param", methods=["POST"])
def post_param_with_inline_concat():
# ruleid: path-traversal-open
with open(flask.request.form['param'] + '.csv', 'r') as fin:
data = json.load(fin)
return data
@app.route("/subexpression", methods=["POST"])
def subexpression():
param = "{}".format(flask.request.form['param'])
print("do things")
# ruleid: path-traversal-open
return open(param, 'r').read()
@app.route("/ok")
def ok():
# ok: path-traversal-open
open("static/path.txt", 'r')
Short Link: https://sg.run/PJRW