generic.nginx.security.dynamic-proxy-host.dynamic-proxy-host

Community Favorite
profile photo of semgrepsemgrep
Author
81,049
Download Count*

The host for this proxy URL is dynamically determined. This can be dangerous if the host can be injected by an attacker because it may forcibly alter destination of the proxy. Consider hardcoding acceptable destinations and retrieving them with 'map' or something similar.

Run Locally

Run in CI

Defintion

rules:
  - id: dynamic-proxy-host
    paths:
      include:
        - "*.conf"
        - "*.vhost"
        - sites-available/*
        - sites-enabled/*
    languages:
      - generic
    severity: WARNING
    message: The host for this proxy URL is dynamically determined. This can be
      dangerous if the host can be injected by an attacker because it may
      forcibly alter destination of the proxy. Consider hardcoding acceptable
      destinations and retrieving them with 'map' or something similar.
    metadata:
      source-rule-url: https://github.com/yandex/gixy/blob/master/docs/en/plugins/ssrf.md
      references:
        - https://nginx.org/en/docs/http/ngx_http_map_module.html
      category: security
      technology:
        - nginx
      confidence: MEDIUM
      cwe:
        - "CWE-441: Unintended Proxy or Intermediary ('Confused Deputy')"
      owasp:
        - A01:2021 - Broken Access Control
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Server-Side Request Forgery (SSRF)
    pattern-either:
      - pattern: proxy_pass $SCHEME://$$HOST ...;
      - pattern: proxy_pass $$SCHEME://$$HOST ...;

Examples

dynamic-proxy-host.conf

server {
  listen              443 ssl;
  server_name         www.example.com;
  keepalive_timeout   70;

  ssl_certificate     www.example.com.crt;
  ssl_certificate_key www.example.com.key;

  location ~ /proxy2/(.*)/(.*)/(.*)$ {
    # ruleid: dynamic-proxy-host
    proxy_pass $1://$2/$3;
  }

  location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_path>.*)$ {
    internal;

    # ruleid: dynamic-proxy-host
    proxy_pass $proxy_proto://$proxy_host/$proxy_path ;
    proxy_set_header Host $proxy_host;
}

  location ~ /proxy3/(.*)/(.*)/(.*)$ {
    # ruleid: dynamic-proxy-host
    proxy_pass http://$2/$3/$1;
  }

  location ~ /proxy4/(.*)/(.*)/(.*)$ {
    # ruleid: dynamic-proxy-host
    proxy_pass https://$1/$2/$3;
  }

  location ~ /proxy5/(.*)/(.*)/(.*)$ {
    # ok: dynamic-proxy-host
    proxy_pass http://blah.com/$3/$1;
  }

  location ~ /proxy6/(.*)/(.*)/(.*)$ {
    # ok: dynamic-proxy-host
    proxy_pass https://blah.com/$2/$3;
  }
}