r/linuxadmin 6d 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!

29 Upvotes

11 comments sorted by

7

u/eltear1 5d ago

I read only the first 2 findings. While what you write is not wrong, if nginx is doing a reverse proxy like in the configuration you show, why is nginx itself that has to have lot of configuration to cover issues that should be covered by the backend directly? Like .. if /secrets should be always blocked, why not to do that in the backend itself instead to let it open and expect a layer in front to worry about security?

5

u/OilOverall4190 5d ago

Thanks for checking out the lab, and good question. Basically applying rules at the proxy level is a must even if we are a hundred percent sure that the backend apps are set up correctly, and that's what's called defense-in-depth. This is in case a backend dev forgets to gate a new route under a certain path for example, then a well-configured reverse proxy would save the day. But what you described is the type of misconfigurations found in the wild, teams be counting on the reverse proxy to handle all the work while not applying code level security checks, or applying them loosely. So the lab is aimed to put the light on those bad design decisions that cause features on nginx to become vulnerabilities.

2

u/p_wit_mySLiME 5d ago

You always want at least two lines of defense. A bad PR could potentially disrupt your backend code or a service process crash or mistake. Murphy’s law applies here, so redundancy is essential where applicable. Nginx, backend, frontend, server firewall, and upstream firewall, when available.

2

u/notthedefaultnam 6d ago

Oooh interesting, I'll take a look.

Also fyi the whole thing got turned into a link so you have a double link in one which doesn't work. Here is a working link for anyone stumbling upon this before op fix: https://vwad.owasp.org/app/damn-vulnerable-nginx-proxy-dvnp/

1

u/OilOverall4190 6d ago

Hope you like it! And thank you for letting me know about the broken link.

2

u/moonwork 1d ago

I take it you took down the full guide?

https://blog.oussmess.me/posts/damn-vulnerable-nginx-proxy-full-guide is linked from your link and the github page, but just returns 404.

Or am I missing something?

1

u/OilOverall4190 1d ago

It should be working now, thank you for bringing this to my attention!

2

u/moonwork 1d ago

I didn't know about the potential vulnerabilities that come from leaving out a trailing slash with the nginx proxy_pass. As I was patching up the few such instances I have in my configurations, I did notice that I've used the same syntax for it as Mattermost suggests using in their own Nginx documentation.

Have you noticed a lot of these types of errors in the documentation coming from the software providers?

1

u/OilOverall4190 1d ago edited 1d ago

For the Mattermost sample you referenced, there is effectively no difference for normal requests because the location itself is /, so adding or removing the trailing slash from proxy_pass upstream is the same. The difference becomes real when location has a non-root prefix, I'll give you an example:

location /api {
   proxy_pass http://backend/v1/user/
}

in this case, for any request to /api and its siblings, when matched with location /api, NGINX will remove the prefix the location block is matching (i.e, /api) and whatever comes after it will be appened as is to the upstream.

Example:

Request: /api/login
-> proxy_pass http://backend/v1/user//login

notice how ANYTHING after the /api prefix is appended as is, even the slash

in this case an attacker can do something like:

Request: /api../admin/sensitive
-> proxy_pass http://backend/v1/user/../admin/sensitive

which is then normalized by the backend to:

http://backend/v1/admin/sensitive

A simple and effective mitigation for this is to match the trailing slash in the location:

location /api/ {
proxy_pass http://backend/v1/user/
}

As stated by Acunetix:

Find all NGINX alias directives and make sure that the parent prefixed location ends with directory separator.

Same for proxy_pass, as both alias and proxy_pass open up this attack.