Bug bounty tips for nginx $request_uri path traversal bypass

Posted on Nov 27, 2021

In this article, I will extend topic by bug bounty tips for weaknesses in authentication/authorization implementation in relation to nginx’s $request_uri variable.

APIs

This vulnerability is for APIs. Best scenario are microservice deployed to Kubernetes and exposed by ingress controller.

Using paths

API that you are playing with, need to use paths to address services, e.g.:

OK!
https://api.example.com/user-service
https://api.example.com/customer-service
...
NOT OK!
https://user.example.com/
https://customer.example.com/

First set of URLs is good for exploitation, as you can try sending request with https://api.example.com/user-service/..%2F/customer-service/endpoint1

Using nginx based ingress controller

In this point we have having two condition, using Kubernetes and using nginx based ingress controller, e.g.: kong, Apache APISIX, F5 NGINX. 

Kubernetes is used in many organizations right now. If you see that API consists of multiply services, you can safely bet on Kubernetes as orchestration. 

To verify if specific ingress is in place you can try to get error message, e.g.: curl --path-as-is https://api.example.com/sdalksjdeiu23432/cutomer-serivice/endpoint1

This sdalksjdeiu23432 is just not existing service. You can see that there is nginx in response.

Normalization of ../ and ..%2F

It’s good to check what is happening for normalization of paths. Between your machine and ingress could be other servers, e.g: additional proxies or WAF (Web Application Firewall).

curl --path-as-is https://api.example.com/sdalksjdeiu23432/../cutomer-serivice/endpoint1
curl --path-as-is https://api.example.com/sdalksjdeiu23432/..%2F/cutomer-serivice/endpoint1
curl --path-as-is https://api.example.com/sdalksjdeiu23432/..%252Fcutomer-serivice/endpoint1 # double encoding

Comparing results could give you idea about path normalization.

External authentication service

This is quite hard to investigate. Idea behind external authentication service is about having it centralized. Having broken authentication proof (e.g. JWT) would issue 401/403 on ingress rather than on upstream.

I would follow those steps:

  1. Login into application
  2. Get some request to backend service
  3. Change it in a way that authentication proof is broken. For JWT it would be just to place any character into it.
  4. Send changed request and see results

Something that you would like to see is:

If you cannot get any indication whether centralized authentication is in place, you can also assume so and try to exploit.

Centralized authorization

Authentication service is checking if you are who you are talking to be. But authorization is making decisions about letting you do some action. Having it centralized in some way is necessary for exploitation. If backend services are doing access control on they own, there is no way to exploit it with presented bypass.

You can do assumption here, that there is centralized authorization and move on.

Exploitation

Public service

Try to find service that is handling requests for anyone. Without any authentication proof. Some kind of public service. If you have one, that’s good, if you don’t have there is still one thing you can do (described in next paragraph).

OK. We have some public-service and also protected-service that is only for logged in users (e.g. with valid JWT token). 

Do some tests:

  1. Take a valid request to protected service, e.g. /protected-service/protected?a=1 and change it to /public-service/..%2Fprotected-service/protected?a=1 but send it without any token
  2. Make token invalid and send request from point 1.
  3. Wait and make token expired and send request from point 1.

What responses did you get? In case of luck you are already getting valid response for point 1. If not maybe point 2 or 3 was successful for you. If not try with different public and protected services. If you still get no valid response it means that there is no vulnerability here.

Privilege escalation

There could be implementation of centralized access control that is checking to which group/role user belong.

In this situation try following steps:

  1. Find endpoint that you cannot access. 
  2. Take a valid request with authentication proof (e.g. JWT).
  3. Send request to endpoint from point 1, but using path traversal described in previous paragraph.

If you didn’t success it means that there is no vulnerability here. Sadly… ☹️

Summary

I have presented steps that can be inspiration for you. Do not limit yourself and be creative. Happy hunting!


Thanks for reading! You can follow me on Twitter.