Old but GOLD Dot Dot Slash to Get the Flag — Uber Microservice

Uber is built on a bunch of microservices, naturally, if you want to interact with microservice, you may want to use some REST apis to do it. Say you want to fetch the driver’s past trip history, you call an API that looks like


Obviously, all of these are performed in the backend, because usually the internal microservices have no permission check or other security measure to prevent IDOR attack. What’s the point to implement authorization check if all of these API calls are predefined path/variables/host. Users can’t control the call anyway, why bother.

This is only true when user really can’t control the API call, back in early 2018, I found an interesting endpoint in partners.uber.com to fetch for monthly statement of driver, that looks something like this.


This is call itself has nothing useful but the response is really the reason I got interested

  "request": {
    "uri": {
      "protocol": "http:",
      "slashes": true,
      "auth": null,
      "host": "",
      "port": "123",
      "hostname": "",
      "hash": null,
      "search": "?earnings_structure_type=&locale=en&user_id=xxxxx",
      "query": "earnings_structure_type=&locale=en&user_id=xxxxx",
      "pathname": "/v1/partners/xxxxx/statements/current",
      "path": "/v1/partners/xxxxxx/statements/current?earnings_structure_type=&locale=en&user_id=xxxxx",
      "href": ""

It is obvious that the API call is taking current in the https://partners.uber.com/p3/money/statements/view/current, and take current and append it to the end of /v1/partners/xxxxxx/statements/, as the response suggests. Also the query part is added to the call as well. The full internal GET request looks like this

It is very interesting because of two observations from the response, first big one is that it has the access token of your uber user, and we know why this is interesting.

Second one is that there is no x-auth-header or authorization headers in the request, yet it still return the access token of user in response! It means if we can somehow manipulate the request change my_user_uuid to victim_uuid in the request. Then we can takeover victim’s account by getting their access token from the response

I need to find an endpoint that allow me to do the following things

  • Pass any parameter to that internal GET request
  • Pass encoded character the that internal GET request to get rid of the unnecessary query in behind (%23, i.e. # can break the query part)
  • View the full response

It turns out, a very similar request allowed me to do all that


Response of the GET request

"href": ""

I think the statement uuid 4cb88fb1-d3fa-3a10-e3b5-ceef8ca71faa is passed to the internal API GET request for both path and query part. I verifed that by sending this request


And the response is still the same, it proves ../ is useful for escaping the path! So it is clear what should we do next. Escape all the way through to root, then craft a request looks just like the one that would return access token in response, and cancel the unnecessary part using #

Target request we want to call

Request that is under our control

And this is the final call I came up with


The response is just as expected

And now we can get any user’s access token by changing the VICTIM_UUID in the request.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s