python.django.security.injection.path-traversal.path-traversal-file-name.path-traversal-file-name
Verifed by r2c
Community Favorite
semgrep
Author
99,207
Download Count*
License
Data from request is passed to a file name $FILE
. This is a path traversal vulnerability, which can lead to sensitive data being leaked. To mitigate, consider using os.path.abspath or os.path.realpath or the pathlib library.
Run Locally
Run in CI
Defintion
rules:
- id: path-traversal-file-name
message: Data from request is passed to a file name `$FILE`. This is a path
traversal vulnerability, which can lead to sensitive data being leaked. To
mitigate, consider using os.path.abspath or os.path.realpath or the
pathlib library.
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:
- django
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: LOW
impact: MEDIUM
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Path Traversal
patterns:
- pattern-inside: |
def $F(...):
...
- pattern-not-inside: |
def $F(...):
...
os.path.realpath(...)
...
- pattern-not-inside: |
def $F(...):
...
os.path.abspath(...)
...
- pattern-either:
- pattern: |
$V = request.$W.get($X)
...
$FILE % ($V)
- pattern: |
$V = request.$W[$X]
...
$FILE % ($V)
- pattern: |
$V = request.$W($X)
...
$FILE % ($V)
- pattern: |
$V = request.$W
...
$FILE % ($V)
# match format use cases
- pattern: |
$V = request.$W.get($X)
...
$FILE.format(..., $V, ...)
- pattern: |
$V = request.$W[$X]
...
$FILE.format(..., $V, ...)
- pattern: |
$V = request.$W($X)
...
$FILE.format(..., $V, ...)
- pattern: |
$V = request.$W
...
$FILE.format(..., $V, ...)
- metavariable-regex:
metavariable: $FILE
regex: .*\.(log|zip|txt|csv|xml|html).*
languages:
- python
severity: WARNING
Examples
path-traversal-file-name.py
import logging
import subprocess
def post1(request, format=None):
try:
# ruleid: path-traversal-file-name
app_log_path = request.data['app_log_path']
host = request.data['host']
connect = connect_init(host)
commands = "find %s -name '*.log'" % (app_log_path)
result = connect.run(commands).stdout
res = []
for i in result.split():
res.append(i)
res = filter(None, res)
connect.close()
http_status = OK
except:
print("foo")
def post2(request, format=None):
try:
# ruleid: path-traversal-file-name
app_log_path = request.data['app_log_path']
host = request.data['host']
connect = connect_init(host)
commands = 'hours_{0}.csv'.format(app_log_path)
result = connect.run(commands).stdout
res = []
for i in result.split():
res.append(i)
res = filter(None, res)
connect.close()
http_status = OK
except:
print("foo")
def post3(request, format=None):
try:
# ok: path-traversal-file-name
app_log_path = request.data['app_log_path']
app_log_path = os.path.abspath(app_log_path)
host = request.data['host']
connect = connect_init(host)
commands = "find %s -name '*.log'" % (app_log_path)
result = connect.run(commands).stdout
res = []
for i in result.split():
res.append(i)
res = filter(None, res)
connect.close()
http_status = OK
except:
print("foo")
def post4(request, format=None):
# ok: path-traversal-file-name
filename = request.GET.get('filename')
host = request.data['host']
commands = "find %s -name ." % (filename)
result = subprocess.check_output(commands)
logging.info("{} ran command: {}".format(host, commands))
Short Link: https://sg.run/BkO2