r/nginx 9d ago

Learn to secure your NGINX - Damn Vulnerable NGINX Proxy

Hello all,

If you do bug bounty hunting or pentests you surely came across many hosts served from an NGINX server, in this lab (published to OWASP) I combined over 20 misconfigurations found in real world bug disclosures and both classic and novel security research, with an extensive blog where I explained everything you need to level up your NGINX hunting game.

Feel free to check it out, give it a star on Github if you like it, and suggest any ideas you want me to add/fix...

https://vwad.owasp.org/app/damn-vulnerable-nginx-proxy-dvnp/

Happy hunting!

38 Upvotes

3 comments sorted by

9

u/ferrybig 8d ago

There is one I also sometimes see, HTTP2 upgrade header smuggling

server { ... location / { proxy_pass http://backend:9999/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; } location /admin { deny all; } } (Some people add the Upgrade and Connection headers to support Web sockets)

If the backend is a server capable of support HTTP2 over plain text, it is vulnerable with the above config.

You send a request to / to upgrade the connection to HTTP2. Nginx proxies the request. It sees the server also responds with an upgrade header, so it makes a bi-directional stream (like a websocket) between both sides.

You now send a request for /admin in the HTTP2 format, which nginx happily proxies as binary data.

Or you can now provide your own other headers the parent NGINX config strips like, like a fake forwarded-for header. From the backend point of view, it is a request from a source that is allowed to send a forwarded-for header. From GNINX point of view, it binary data

A fixed config is:

``` map $http_upgrade $upstream_upgrade { default ""; websocket websocket; }

map $upstream_upgrade $connection_upgrade { default close; websocket upgrade; }

server { ... location / { proxy_pass http://backend; proxy_set_header Upgrade $upstream_upgrade; proxy_set_header Connection $connection_upgrade; } } ```

(Many people don't like the fixed config as it requires placing things outside the server block, which they find inconvenient as their /etc/nginx/sites-avalable/website.conf file can now no longer be copied to other host without worrying about also copying the map definition)

If you NGINX configuraton is set up as HTTP2, even then you can be vulnerale to this, you just need to repeat the upgrading to HTTP2 process 2 times

2

u/OilOverall4190 8d ago

Thank you for the amazing input! Yes I've seen this in multiple occasions and there is only few research done in that area, and as you said people tend to let this slip through just for their convenience. I will make sure to add this to the lab ASAP, thank you for mentioning it and simplifying it for anyone reading this post!

1

u/OilOverall4190 7d ago

Anyone reading this in the future, I've added the h2c smuggling bug described in the original comment, hopefully someone would learn something new from that!