python.django.security.injection.ssrf.ssrf-injection-urllib.ssrf-injection-urllib
semgrep
Author
6,591
Download Count*
License
Data from request object is passed to a new server-side request. This could lead to a server-side request forgery (SSRF), which could result in attackers gaining access to private organization data. To mitigate, ensure that schemes and hosts are validated against an allowlist, do not forward the response to the user, and ensure proper authentication and transport-layer security in the proxied request.
Run Locally
Run in CI
Defintion
rules:
- id: ssrf-injection-urllib
message: Data from request object is passed to a new server-side request. This
could lead to a server-side request forgery (SSRF), which could result in
attackers gaining access to private organization data. To mitigate, ensure
that schemes and hosts are validated against an allowlist, do not forward
the response to the user, and ensure proper authentication and
transport-layer security in the proxied request.
metadata:
cwe:
- "CWE-918: Server-Side Request Forgery (SSRF)"
owasp:
- A10:2021 - Server-Side Request Forgery (SSRF)
references:
- https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
category: security
technology:
- django
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: MEDIUM
impact: HIGH
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Server-Side Request Forgery (SSRF)
languages:
- python
severity: ERROR
patterns:
- pattern-inside: |
def $FUNC(...):
...
- pattern-either:
- pattern: urllib.request.urlopen(..., $S.format(..., request.$W.get(...), ...),
...)
- pattern: urllib.request.urlopen(..., $S % request.$W.get(...), ...)
- pattern: urllib.request.urlopen(..., f"...{request.$W.get(...)}...", ...)
- pattern: urllib.request.urlopen(..., request.$W.get(...), ...)
- pattern: |
$DATA = request.$W.get(...)
...
urllib.request.urlopen(..., $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
urllib.request.urlopen(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR % $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
urllib.request.urlopen(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = f"...{$DATA}..."
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W.get(...)
...
urllib.request.urlopen(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W.get(...)
...
$INTERM = $STR + $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: $A = urllib.request.urlopen(..., request.$W.get(...), ...)
- pattern: return urllib.request.urlopen(..., request.$W.get(...), ...)
- pattern: urllib.request.urlopen(..., $S.format(..., request.$W(...), ...), ...)
- pattern: urllib.request.urlopen(..., $S % request.$W(...), ...)
- pattern: urllib.request.urlopen(..., f"...{request.$W(...)}...", ...)
- pattern: urllib.request.urlopen(..., request.$W(...), ...)
- pattern: |
$DATA = request.$W(...)
...
urllib.request.urlopen(..., $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR.format(..., $DATA, ...)
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
urllib.request.urlopen(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR % $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
urllib.request.urlopen(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = f"...{$DATA}..."
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W(...)
...
urllib.request.urlopen(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W(...)
...
$INTERM = $STR + $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: $A = urllib.request.urlopen(..., request.$W(...), ...)
- pattern: return urllib.request.urlopen(..., request.$W(...), ...)
- pattern: urllib.request.urlopen(..., $S.format(..., request.$W[...], ...), ...)
- pattern: urllib.request.urlopen(..., $S % request.$W[...], ...)
- pattern: urllib.request.urlopen(..., f"...{request.$W[...]}...", ...)
- pattern: urllib.request.urlopen(..., request.$W[...], ...)
- pattern: |
$DATA = request.$W[...]
...
urllib.request.urlopen(..., $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR.format(..., $DATA, ...)
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
urllib.request.urlopen(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR % $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
urllib.request.urlopen(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = f"...{$DATA}..."
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W[...]
...
urllib.request.urlopen(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W[...]
...
$INTERM = $STR + $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: $A = urllib.request.urlopen(..., request.$W[...], ...)
- pattern: return urllib.request.urlopen(..., request.$W[...], ...)
- pattern: urllib.request.urlopen(..., $S.format(..., request.$W, ...), ...)
- pattern: urllib.request.urlopen(..., $S % request.$W, ...)
- pattern: urllib.request.urlopen(..., f"...{request.$W}...", ...)
- pattern: urllib.request.urlopen(..., request.$W, ...)
- pattern: |
$DATA = request.$W
...
urllib.request.urlopen(..., $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
urllib.request.urlopen(..., $STR.format(..., $DATA, ...), ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR.format(..., $DATA, ...)
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
urllib.request.urlopen(..., $STR % $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR % $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
urllib.request.urlopen(..., f"...{$DATA}...", ...)
- pattern: |
$DATA = request.$W
...
$INTERM = f"...{$DATA}..."
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: |
$DATA = request.$W
...
urllib.request.urlopen(..., $STR + $DATA, ...)
- pattern: |
$DATA = request.$W
...
$INTERM = $STR + $DATA
...
urllib.request.urlopen(..., $INTERM, ...)
- pattern: $A = urllib.request.urlopen(..., request.$W, ...)
- pattern: return urllib.request.urlopen(..., request.$W, ...)
Examples
ssrf-injection-urllib.py
def test1():
from urllib.request import urlopen
from django.shortcuts import render
def send_to_redis(request):
# ruleid: ssrf-injection-urllib
bucket = request.GET.get("bucket")
inner_response = urlopen("http://my.redis.foo/{}".format(bucket), data=3)
return render({"response_code": inner_response.status_code})
def test2():
from urllib.request import urlopen
from django.http import HttpResponse
def send_to_redis(request):
# ruleid: ssrf-injection-urllib
bucket = request.GET.get("bucket")
inner_response = urlopen("http://my.redis.foo/{}".format(bucket), data=3)
return HttpResponse(body = {"response_code": inner_response.status_code})
Short Link: https://sg.run/6n2B