python.django.security.injection.ssrf.ssrf-injection-requests.ssrf-injection-requests

profile photo of semgrepsemgrep
Author
6,591
Download Count*

Data from request object is passed to a new server-side request. This could lead to a server-side request forgery (SSRF). 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. See https://owasp.org/www-community/attacks/Server_Side_Request_Forgery to learn more about SSRF vulnerabilities.

Run Locally

Run in CI

Defintion

rules:
  - id: ssrf-injection-requests
    message: Data from request object is passed to a new server-side request. This
      could lead to a server-side request forgery (SSRF). 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. See
      https://owasp.org/www-community/attacks/Server_Side_Request_Forgery to
      learn more about SSRF vulnerabilities.
    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: requests.$METHOD(..., $S.format(..., request.$W.get(...), ...), ...)
          - pattern: requests.$METHOD(..., $S % request.$W.get(...), ...)
          - pattern: requests.$METHOD(..., f"...{request.$W.get(...)}...", ...)
          - pattern: requests.$METHOD(..., request.$W.get(...), ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              requests.$METHOD(..., $DATA, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              $INTERM = $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              requests.$METHOD(..., $STR.format(..., $DATA, ...), ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              $INTERM = $STR.format(..., $DATA, ...)
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              requests.$METHOD(..., $STR % $DATA, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              $INTERM = $STR % $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              requests.$METHOD(..., f"...{$DATA}...", ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              $INTERM = f"...{$DATA}..."
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              requests.$METHOD(..., $STR + $DATA, ...)
          - pattern: |
              $DATA = request.$W.get(...)
              ...
              $INTERM = $STR + $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: $A = requests.$METHOD(..., request.$W.get(...), ...)
          - pattern: return requests.$METHOD(..., request.$W.get(...), ...)
          - pattern: requests.$METHOD(..., $S.format(..., request.$W(...), ...), ...)
          - pattern: requests.$METHOD(..., $S % request.$W(...), ...)
          - pattern: requests.$METHOD(..., f"...{request.$W(...)}...", ...)
          - pattern: requests.$METHOD(..., request.$W(...), ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              requests.$METHOD(..., $DATA, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              $INTERM = $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              requests.$METHOD(..., $STR.format(..., $DATA, ...), ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              $INTERM = $STR.format(..., $DATA, ...)
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              requests.$METHOD(..., $STR % $DATA, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              $INTERM = $STR % $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              requests.$METHOD(..., f"...{$DATA}...", ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              $INTERM = f"...{$DATA}..."
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              requests.$METHOD(..., $STR + $DATA, ...)
          - pattern: |
              $DATA = request.$W(...)
              ...
              $INTERM = $STR + $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: $A = requests.$METHOD(..., request.$W(...), ...)
          - pattern: return requests.$METHOD(..., request.$W(...), ...)
          - pattern: requests.$METHOD(..., $S.format(..., request.$W[...], ...), ...)
          - pattern: requests.$METHOD(..., $S % request.$W[...], ...)
          - pattern: requests.$METHOD(..., f"...{request.$W[...]}...", ...)
          - pattern: requests.$METHOD(..., request.$W[...], ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              requests.$METHOD(..., $DATA, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              $INTERM = $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              requests.$METHOD(..., $STR.format(..., $DATA, ...), ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              $INTERM = $STR.format(..., $DATA, ...)
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              requests.$METHOD(..., $STR % $DATA, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              $INTERM = $STR % $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              requests.$METHOD(..., f"...{$DATA}...", ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              $INTERM = f"...{$DATA}..."
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              requests.$METHOD(..., $STR + $DATA, ...)
          - pattern: |
              $DATA = request.$W[...]
              ...
              $INTERM = $STR + $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: $A = requests.$METHOD(..., request.$W[...], ...)
          - pattern: return requests.$METHOD(..., request.$W[...], ...)
          - pattern: requests.$METHOD(..., $S.format(..., request.$W, ...), ...)
          - pattern: requests.$METHOD(..., $S % request.$W, ...)
          - pattern: requests.$METHOD(..., f"...{request.$W}...", ...)
          - pattern: requests.$METHOD(..., request.$W, ...)
          - pattern: |
              $DATA = request.$W
              ...
              requests.$METHOD(..., $DATA, ...)
          - pattern: |
              $DATA = request.$W
              ...
              $INTERM = $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W
              ...
              requests.$METHOD(..., $STR.format(..., $DATA, ...), ...)
          - pattern: |
              $DATA = request.$W
              ...
              $INTERM = $STR.format(..., $DATA, ...)
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W
              ...
              requests.$METHOD(..., $STR % $DATA, ...)
          - pattern: |
              $DATA = request.$W
              ...
              $INTERM = $STR % $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W
              ...
              requests.$METHOD(..., f"...{$DATA}...", ...)
          - pattern: |
              $DATA = request.$W
              ...
              $INTERM = f"...{$DATA}..."
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: |
              $DATA = request.$W
              ...
              requests.$METHOD(..., $STR + $DATA, ...)
          - pattern: |
              $DATA = request.$W
              ...
              $INTERM = $STR + $DATA
              ...
              requests.$METHOD(..., $INTERM, ...)
          - pattern: $A = requests.$METHOD(..., request.$W, ...)
          - pattern: return requests.$METHOD(..., request.$W, ...)

Examples

ssrf-injection-requests.py

def test_bad_1():
    from requests import get
    from django.shortcuts import render

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.GET.get("bucket")
        inner_response = get("http://my.redis.foo/{}".format(bucket), data=3)
        return render({"response_code": inner_response.status_code})

def test_bad_2():
    from requests import get
    from django.http import HttpResponse

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.GET.get("bucket")
        inner_response = get("http://my.redis.foo/{}".format(bucket), data=3)
        return HttpResponse(body = {"response_code": inner_response.status_code})

def test_bad_3():
    from requests import get
    from django.shortcuts import render

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.GET.get("bucket")
        inner_response = get(f"http://my.redis.foo/{bucket}", data=3)
        return render({"response_code": inner_response.status_code})

def test_bad_4():
    from requests import get
    from django.shortcuts import render

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.headers.get("bucket")
        inner_response = get("http://my.redis.foo/{}".format(bucket), data=3)
        return render({"response_code": inner_response.status_code})

def test_bad_5():
    from requests import get
    from django.shortcuts import render

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.GET["bucket"]
        inner_response = get("http://my.redis.foo/{}".format(bucket), data=3)
        return render({"response_code": inner_response.status_code})

def test_bad_6():
    from requests import get
    from django.shortcuts import render

    def send_to_redis(request):
        # ruleid: ssrf-injection-requests
        bucket = request.headers["bucket"]
        inner_response = get("http://my.redis.foo/{}".format(bucket), data=3)
        return render({"response_code": inner_response.status_code})