# OAuth do przejęcia konta {{#include ../banners/hacktricks-training.md}} ## Podstawowe informacje OAuth oferuje różne wersje, z podstawowymi informacjami dostępnymi w [dokumentacji OAuth 2.0](https://oauth.net/2/). Ta dyskusja koncentruje się głównie na szeroko stosowanym [typie przyznawania kodu autoryzacji OAuth 2.0](https://oauth.net/2/grant-types/authorization-code/), zapewniającym **ramy autoryzacji, które umożliwiają aplikacji dostęp do konta użytkownika w innej aplikacji lub wykonywanie działań w jego imieniu** (serwer autoryzacji). Rozważmy hipotetyczną stronę internetową _**https://example.com**_, zaprojektowaną w celu **prezentacji wszystkich Twoich postów w mediach społecznościowych**, w tym prywatnych. Aby to osiągnąć, wykorzystuje się OAuth 2.0. _https://example.com_ poprosi o Twoją zgodę na **dostęp do Twoich postów w mediach społecznościowych**. W konsekwencji na _https://socialmedia.com_ pojawi się ekran zgody, przedstawiający **żądane uprawnienia oraz dewelopera składającego prośbę**. Po Twojej autoryzacji, _https://example.com_ zyskuje możliwość **dostępu do Twoich postów w Twoim imieniu**. Ważne jest, aby zrozumieć następujące komponenty w ramach OAuth 2.0: - **właściciel zasobu**: Ty, jako **użytkownik/podmiot**, autoryzujesz dostęp do swojego zasobu, jak posty na Twoim koncie w mediach społecznościowych. - **serwer zasobów**: **serwer zarządzający uwierzytelnionymi żądaniami** po tym, jak aplikacja zabezpieczyła `access token` w imieniu `właściciela zasobu`, np. **https://socialmedia.com**. - **aplikacja kliencka**: **aplikacja ubiegająca się o autoryzację** od `właściciela zasobu`, taka jak **https://example.com**. - **serwer autoryzacji**: **serwer, który wydaje `access tokens`** dla `aplikacji klienckiej` po pomyślnej autoryzacji `właściciela zasobu` i zabezpieczeniu autoryzacji, np. **https://socialmedia.com**. - **client_id**: Publiczny, unikalny identyfikator aplikacji. - **client_secret:** Poufny klucz, znany wyłącznie aplikacji i serwerowi autoryzacji, używany do generowania `access_tokens`. - **response_type**: Wartość określająca **typ żądanego tokena**, jak `code`. - **scope**: **poziom dostępu**, o który `aplikacja kliencka` prosi `właściciela zasobu`. - **redirect_uri**: **URL, na który użytkownik jest przekierowywany po autoryzacji**. Zazwyczaj musi on odpowiadać wcześniej zarejestrowanemu URL przekierowania. - **state**: Parametr do **utrzymywania danych podczas przekierowania użytkownika do i z serwera autoryzacji**. Jego unikalność jest kluczowa jako **mechanizm ochrony przed CSRF**. - **grant_type**: Parametr wskazujący **typ przyznania i typ tokena, który ma być zwrócony**. - **code**: Kod autoryzacji z `serwera autoryzacji`, używany razem z `client_id` i `client_secret` przez aplikację kliencką do uzyskania `access_token`. - **access_token**: **token, którego aplikacja kliencka używa do żądań API** w imieniu `właściciela zasobu`. - **refresh_token**: Umożliwia aplikacji **uzyskanie nowego `access_token` bez ponownego pytania użytkownika**. ### Przepływ **Rzeczywisty przepływ OAuth** przebiega następująco: 1. Przechodzisz do [https://example.com](https://example.com) i wybierasz przycisk „Integruj z mediami społecznościowymi”. 2. Strona wysyła żądanie do [https://socialmedia.com](https://socialmedia.com) z prośbą o Twoją autoryzację, aby aplikacja https://example.com mogła uzyskać dostęp do Twoich postów. Żądanie jest skonstruowane w następujący sposób: ``` https://socialmedia.com/auth ?response_type=code &client_id=example_clientId &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback &scope=readPosts &state=randomString123 ``` 3. Następnie zostaniesz przedstawiony stronie zgody. 4. Po twojej akceptacji, Social Media wysyła odpowiedź do `redirect_uri` z parametrami `code` i `state`: ``` https://example.com?code=uniqueCode123&state=randomString123 ``` 5. https://example.com wykorzystuje ten `code`, razem z jego `client_id` i `client_secret`, aby złożyć żądanie po stronie serwera w celu uzyskania `access_token` w Twoim imieniu, umożliwiając dostęp do uprawnień, na które wyraziłeś zgodę: ``` POST /oauth/access_token Host: socialmedia.com ...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"} ``` 6. Na koniec proces kończy się, gdy https://example.com wykorzystuje twój `access_token`, aby wykonać wywołanie API do Social Media w celu uzyskania dostępu ## Luki ### Otwarty redirect_uri `redirect_uri` jest kluczowy dla bezpieczeństwa w implementacjach OAuth i OpenID, ponieważ kieruje, gdzie wrażliwe dane, takie jak kody autoryzacji, są wysyłane po autoryzacji. Jeśli jest źle skonfigurowany, może pozwolić atakującym na przekierowanie tych żądań do złośliwych serwerów, co umożliwia przejęcie konta. Techniki eksploatacji różnią się w zależności od logiki walidacji serwera autoryzacji. Mogą obejmować od ścisłego dopasowania ścieżek do akceptowania dowolnego URL w określonej domenie lub podkatalogu. Powszechne metody eksploatacji obejmują otwarte przekierowania, przechodzenie przez ścieżki, wykorzystywanie słabych wyrażeń regularnych oraz wstrzykiwanie HTML w celu kradzieży tokenów. Oprócz `redirect_uri`, inne parametry OAuth i OpenID, takie jak `client_uri`, `policy_uri`, `tos_uri` i `initiate_login_uri`, są również podatne na ataki przekierowujące. Parametry te są opcjonalne, a ich wsparcie różni się w zależności od serwerów. Dla tych, którzy celują w serwer OpenID, punkt końcowy odkrywania (`**.well-known/openid-configuration**`) często zawiera cenne szczegóły konfiguracyjne, takie jak `registration_endpoint`, `request_uri_parameter_supported` i "`require_request_uri_registration`. Te szczegóły mogą pomóc w identyfikacji punktu końcowego rejestracji i innych specyfikacji konfiguracyjnych serwera. ### XSS w implementacji przekierowania Jak wspomniano w tym raporcie o bug bounty [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html), może być możliwe, że **URL przekierowania jest odzwierciedlany w odpowiedzi** serwera po uwierzytelnieniu użytkownika, co czyni go **podatnym na XSS**. Możliwy ładunek do przetestowania: ``` https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard

test

``` ### CSRF - Niewłaściwe zarządzanie parametrem state W implementacjach OAuth, niewłaściwe użycie lub pominięcie **parametru `state`** może znacznie zwiększyć ryzyko ataków **Cross-Site Request Forgery (CSRF)**. Ta podatność pojawia się, gdy parametr `state` jest **nieużywany, używany jako statyczna wartość lub nieprawidłowo walidowany lub powiązany z sesją użytkownika** podczas logowania, co pozwala atakującym na ominięcie ochrony CSRF. Atakujący mogą to wykorzystać, przechwytując proces autoryzacji, aby powiązać swoje konto z kontem ofiary, co prowadzi do potencjalnych **przejęć kont** poprzez zmuszenie użytkownika do zalogowania się za pomocą prawie zakończonego przepływu oauth należącego do atakującego. Jest to szczególnie krytyczne w aplikacjach, w których OAuth jest używany do **celów uwierzytelniania**. Przykłady tej podatności w rzeczywistych sytuacjach zostały udokumentowane w różnych **wyzwaniach CTF** i **platformach hackingowych**, podkreślając jej praktyczne implikacje. Problem ten dotyczy również integracji z usługami stron trzecich, takimi jak **Slack**, **Stripe** i **PayPal**, gdzie atakujący mogą przekierowywać powiadomienia lub płatności na swoje konta. Właściwe zarządzanie i walidacja **parametru `state`** są kluczowe dla ochrony przed CSRF i zabezpieczenia przepływu OAuth. ### Przed przejęciem konta 1. **Bez weryfikacji e-maila przy tworzeniu konta**: Atakujący mogą z wyprzedzeniem stworzyć konto używając e-maila ofiary. Jeśli ofiara później użyje usługi stron trzecich do logowania, aplikacja może nieumyślnie powiązać to konto z wcześniej stworzonym kontem atakującego, co prowadzi do nieautoryzowanego dostępu. 2. **Wykorzystywanie luźnej weryfikacji e-maila w OAuth**: Atakujący mogą wykorzystać usługi OAuth, które nie weryfikują e-maili, rejestrując się w ich usłudze, a następnie zmieniając adres e-mail konta na e-mail ofiary. Ta metoda również niesie ryzyko nieautoryzowanego dostępu do konta, podobnie jak w pierwszym scenariuszu, ale przez inny wektor ataku. ### Ujawnienie sekretów Identyfikacja i ochrona tajnych parametrów OAuth jest kluczowa. Podczas gdy **`client_id`** można bezpiecznie ujawniać, ujawnienie **`client_secret`** stwarza znaczące ryzyko. Jeśli `client_secret` zostanie skompromitowane, atakujący mogą wykorzystać tożsamość i zaufanie aplikacji do **kradzieży `access_tokens` użytkowników** i prywatnych informacji. Powszechna podatność pojawia się, gdy aplikacje błędnie obsługują wymianę `code` autoryzacji na `access_token` po stronie klienta, a nie serwera. Ten błąd prowadzi do ujawnienia `client_secret`, umożliwiając atakującym generowanie `access_tokens` pod przykrywką aplikacji. Ponadto, poprzez inżynierię społeczną, atakujący mogą eskalować uprawnienia, dodając dodatkowe zakresy do autoryzacji OAuth, dalej wykorzystując zaufany status aplikacji. ### Bruteforce sekretu klienta Możesz spróbować **bruteforce'ować client_secret** dostawcy usług z dostawcą tożsamości, aby spróbować ukraść konta.\ Żądanie do BF może wyglądać podobnie do: ``` POST /token HTTP/1.1 content-type: application/x-www-form-urlencoded host: 10.10.10.10:3000 content-length: 135 Connection: close code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce] ``` ### Referer Header leaking Code + State Gdy klient ma **kod i stan**, jeśli są one **odzwierciedlone w nagłówku Referer** podczas przeglądania innej strony, to jest podatny. ### Access Token Stored in Browser History Przejdź do **historii przeglądarki i sprawdź, czy token dostępu jest tam zapisany**. ### Everlasting Authorization Code **Kod autoryzacji powinien żyć tylko przez pewien czas, aby ograniczyć czas, w którym atakujący może go ukraść i użyć**. ### Authorization/Refresh Token not bound to client Jeśli możesz uzyskać **kod autoryzacji i użyć go z innym klientem, to możesz przejąć inne konta**. ### Happy Paths, XSS, Iframes & Post Messages to leak code & state values [**Sprawdź ten post**](https://labs.detectify.com/writeups/account-hijacking-using-dirty-dancing-in-sign-in-oauth-flows/#gadget-2-xss-on-sandbox-third-party-domain-that-gets-the-url) ### AWS Cognito W tym raporcie o bug bounty: [**https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/**](https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/) możesz zobaczyć, że **token**, który **AWS Cognito** zwraca użytkownikowi, może mieć **wystarczające uprawnienia do nadpisania danych użytkownika**. Dlatego, jeśli możesz **zmienić adres e-mail użytkownika na inny adres e-mail**, możesz być w stanie **przejąć** inne konta. ```bash # Read info of the user aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...] # Change email address aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com { "CodeDeliveryDetailsList": [ { "Destination": "i***@f***.com", "DeliveryMedium": "EMAIL", "AttributeName": "email" } ] } ``` Dla bardziej szczegółowych informacji na temat nadużywania AWS cognito sprawdź: {{#ref}} https://cloud.hacktricks.wiki/en/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum.html {{#endref}} ### Nadużywanie tokenów innych aplikacji Jak [**wspomniano w tym artykule**](https://salt.security/blog/oh-auth-abusing-oauth-to-take-over-millions-of-accounts), przepływy OAuth, które oczekują otrzymania **tokena** (a nie kodu), mogą być podatne, jeśli nie sprawdzają, czy token należy do aplikacji. Dzieje się tak, ponieważ **atakujący** może stworzyć **aplikację wspierającą OAuth i logować się za pomocą Facebooka** (na przykład) w swojej własnej aplikacji. Następnie, gdy ofiara loguje się za pomocą Facebooka w **aplikacji atakującego**, atakujący może uzyskać **token OAuth użytkownika przyznany jego aplikacji i użyć go do zalogowania się w aplikacji OAuth ofiary, używając tokena użytkownika ofiary**. > [!OSTRZEŻENIE] > Dlatego, jeśli atakujący zdoła uzyskać dostęp użytkownika do swojej własnej aplikacji OAuth, będzie mógł przejąć konto ofiary w aplikacjach, które oczekują tokena i nie sprawdzają, czy token został przyznany ich identyfikatorowi aplikacji. ### Dwa linki i cookie Zgodnie z [**tym artykułem**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f), możliwe było zmuszenie ofiary do otwarcia strony z **returnUrl** wskazującym na host atakującego. Informacje te byłyby **przechowywane w cookie (RU)**, a w **późniejszym kroku** **prompt** zapyta **użytkownika**, czy chce udzielić dostępu do hosta atakującego. Aby obejść ten prompt, możliwe było otwarcie zakładki w celu zainicjowania **przepływu Oauth**, który ustawiłby to cookie RU używając **returnUrl**, zamknięcie zakładki przed wyświetleniem promptu i otwarcie nowej zakładki bez tej wartości. Wtedy **prompt nie poinformuje o hoście atakującego**, ale cookie zostanie ustawione na niego, więc **token zostanie wysłany do hosta atakującego** w przekierowaniu. ### Obejście interakcji z promptem Jak wyjaśniono w [**tym filmie**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), niektóre implementacje OAuth pozwalają wskazać parametr **`prompt`** jako None (**`&prompt=none`**), aby **zapobiec pytaniu użytkowników o potwierdzenie** przyznanego dostępu w prompt w sieci, jeśli są już zalogowani na platformie. ### response_mode Jak [**wyjaśniono w tym filmie**](https://www.youtube.com/watch?v=n9x7_J_a_7Q), może być możliwe wskazanie parametru **`response_mode`**, aby określić, gdzie chcesz, aby kod został podany w ostatecznym URL: - `response_mode=query` -> Kod jest podawany wewnątrz parametru GET: `?code=2397rf3gu93f` - `response_mode=fragment` -> Kod jest podawany wewnątrz fragmentu URL `#code=2397rf3gu93f` - `response_mode=form_post` -> Kod jest podawany wewnątrz formularza POST z polem o nazwie `code` i wartością - `response_mode=web_message` -> Kod jest wysyłany w wiadomości post: `window.opener.postMessage({"code": "asdasdasd...` ### Przepływ OAuth ROPC - obejście 2 FA Zgodnie z [**tym wpisem na blogu**](https://cybxis.medium.com/a-bypass-on-gitlabs-login-email-verification-via-oauth-ropc-flow-e194242cad96), jest to przepływ OAuth, który pozwala na logowanie się w OAuth za pomocą **nazwa użytkownika** i **hasła**. Jeśli podczas tego prostego przepływu zwrócony zostanie **token** z dostępem do wszystkich działań, które użytkownik może wykonać, to możliwe jest obejście 2FA przy użyciu tego tokena. ### ATO na stronie internetowej przekierowującej na podstawie otwartego przekierowania do referrera Ten [**wpis na blogu**](https://blog.voorivex.team/oauth-non-happy-path-to-ato) opisuje, jak możliwe było nadużycie **otwartego przekierowania** do wartości z **referrera**, aby nadużyć OAuth do ATO. Atak polegał na: 1. Ofiara uzyskuje dostęp do strony internetowej atakującego 2. Ofiara otwiera złośliwy link, a otwieracz rozpoczyna przepływ Google OAuth z `response_type=id_token,code&prompt=none` jako dodatkowymi parametrami, używając jako **referrera strony internetowej atakującego**. 3. W otwieraczu, po autoryzacji ofiary przez dostawcę, wysyła ich z powrotem do wartości parametru `redirect_uri` (strona ofiary) z kodem 30X, który nadal utrzymuje stronę internetową atakującego w refererze. 4. Strona **ofiary wyzwala otwarte przekierowanie na podstawie referrera**, przekierowując użytkownika ofiary na stronę internetową atakującego, ponieważ **`respose_type`** był **`id_token,code`**, kod zostanie wysłany z powrotem do atakującego w **fragmencie** URL, co pozwoli mu przejąć konto użytkownika za pomocą Google na stronie ofiary. ### Parametry SSRFs [**Sprawdź to badanie**](https://portswigger.net/research/hidden-oauth-attack-vectors) **Aby uzyskać dalsze szczegóły na temat tej techniki.** Dynamiczna rejestracja klienta w OAuth służy jako mniej oczywisty, ale krytyczny wektor dla luk w zabezpieczeniach, szczególnie dla ataków **Server-Side Request Forgery (SSRF)**. Ten punkt końcowy pozwala serwerom OAuth na otrzymywanie szczegółów dotyczących aplikacji klienckich, w tym wrażliwych adresów URL, które mogą być wykorzystane. **Kluczowe punkty:** - **Dynamiczna rejestracja klienta** jest często mapowana na `/register` i akceptuje szczegóły takie jak `client_name`, `client_secret`, `redirect_uris` oraz adresy URL dla logo lub zestawów kluczy JSON Web (JWK) za pomocą żądań POST. - Ta funkcja przestrzega specyfikacji określonych w **RFC7591** i **OpenID Connect Registration 1.0**, które zawierają parametry potencjalnie podatne na SSRF. - Proces rejestracji może nieumyślnie narażać serwery na SSRF na kilka sposobów: - **`logo_uri`**: Adres URL dla logo aplikacji klienckiej, który może być pobierany przez serwer, wyzwalając SSRF lub prowadząc do XSS, jeśli adres URL jest źle obsługiwany. - **`jwks_uri`**: Adres URL do dokumentu JWK klienta, który, jeśli zostanie złośliwie skonstruowany, może spowodować, że serwer wykona zewnętrzne żądania do serwera kontrolowanego przez atakującego. - **`sector_identifier_uri`**: Odnosi się do tablicy JSON `redirect_uris`, którą serwer może pobrać, tworząc możliwość SSRF. - **`request_uris`**: Wymienia dozwolone URI żądań dla klienta, które mogą być wykorzystywane, jeśli serwer pobiera te URI na początku procesu autoryzacji. **Strategia eksploatacji:** - SSRF można wyzwolić, rejestrując nowego klienta z złośliwymi adresami URL w parametrach takich jak `logo_uri`, `jwks_uri` lub `sector_identifier_uri`. - Chociaż bezpośrednia eksploatacja za pomocą `request_uris` może być ograniczona przez kontrole białej listy, dostarczenie wcześniej zarejestrowanego, kontrolowanego przez atakującego `request_uri` może ułatwić SSRF podczas fazy autoryzacji. ## Wyścigi warunków dostawców OAuth Jeśli platforma, którą testujesz, jest dostawcą OAuth [**przeczytaj to, aby przetestować możliwe wyścigi warunków**](race-condition.md). ## Atak na zmienne mutowalne W OAuth pole sub unikalnie identyfikuje użytkownika, ale jego format różni się w zależności od serwera autoryzacji. Aby ustandaryzować identyfikację użytkowników, niektórzy klienci używają adresów e-mail lub identyfikatorów użytkowników. Jednak jest to ryzykowne, ponieważ: - Niektóre serwery autoryzacji nie zapewniają, że te właściwości (takie jak e-mail) pozostają niezmienne. - W niektórych implementacjach—takich jak **"Zaloguj się za pomocą Microsoftu"**—klient polega na polu e-mail, które jest **kontrolowane przez użytkownika w Entra ID** i nie jest weryfikowane. - Atakujący może to wykorzystać, tworząc własną organizację Azure AD (np. doyensectestorg) i używając jej do przeprowadzenia logowania Microsoft. - Mimo że identyfikator obiektu (przechowywany w sub) jest niezmienny i bezpieczny, pole e-mail, na którym polega, może umożliwić przejęcie konta (na przykład, przejęcie konta takiego jak victim@gmail.com). ## Atak na mylenie klientów W **Ataku na mylenie klientów**, aplikacja korzystająca z przepływu OAuth Implicit Flow nie weryfikuje, że ostateczny token dostępu jest generowany specjalnie dla jej własnego identyfikatora klienta. Atakujący zakłada publiczną stronę internetową, która korzysta z przepływu OAuth Implicit Flow Google, oszukując tysiące użytkowników na logowanie się i w ten sposób zbierając tokeny dostępu przeznaczone dla strony atakującego. Jeśli ci użytkownicy mają również konta na innej podatnej stronie internetowej, która nie weryfikuje identyfikatora klienta tokena, atakujący może ponownie wykorzystać zebrane tokeny, aby podszyć się pod ofiary i przejąć ich konta. ## Atak na podniesienie zakresu Typ **Authorization Code Grant** obejmuje bezpieczną komunikację serwer-serwer w celu przesyłania danych użytkownika. Jednak jeśli **Serwer Autoryzacji** niejawnie ufa parametrowi zakresu w żądaniu tokena dostępu (parametr nieokreślony w RFC), złośliwa aplikacja może podnieść uprawnienia kodu autoryzacyjnego, żądając wyższego zakresu. Po wygenerowaniu **tokena dostępu** **Serwer Zasobów** musi go zweryfikować: dla tokenów JWT wiąże się to z sprawdzeniem podpisu JWT i wyodrębnieniem danych, takich jak client_id i scope, podczas gdy dla tokenów losowych serwer musi zapytać Serwer Autoryzacji, aby uzyskać szczegóły tokena. ## Przechwytywanie schematu przekierowania W mobilnych implementacjach OAuth aplikacje używają **niestandardowych schematów URI** do odbierania przekierowań z kodami autoryzacyjnymi. Jednak ponieważ wiele aplikacji może zarejestrować ten sam schemat na urządzeniu, założenie, że tylko legalny klient kontroluje URI przekierowania, jest naruszane. Na Androidzie, na przykład, URI intencji takie jak `com.example.app://` oauth jest przechwytywane na podstawie schematu i opcjonalnych filtrów zdefiniowanych w filtrze intencji aplikacji. Ponieważ rozwiązywanie intencji w Androidzie może być szerokie—szczególnie jeśli tylko schemat jest określony—atakujący może zarejestrować złośliwą aplikację z starannie skonstruowanym filtrem intencji, aby przechwycić kod autoryzacyjny. To może **umożliwić przejęcie konta** zarówno poprzez interakcję użytkownika (gdy wiele aplikacji jest uprawnionych do obsługi intencji), jak i za pomocą technik omijających, które wykorzystują zbyt specyficzne filtry, jak opisano w schemacie oceny Ostorlab. ## Odnośniki - [**https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1**](https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1) - [**https://portswigger.net/research/hidden-oauth-attack-vectors**](https://portswigger.net/research/hidden-oauth-attack-vectors) - [**https://blog.doyensec.com/2025/01/30/oauth-common-vulnerabilities.html**](https://blog.doyensec.com/2025/01/30/oauth-common-vulnerabilities.html) {{#include ../banners/hacktricks-training.md}}