• bezpieczeństwo
  • oauth
  • PKCE

Krótkie przypomnienie o zabezpieczeniach OAuth

Jak dobrze znasz środki ochronne stosowane przez OAuth? Czy Twój system przestrzega otwartego standardu OAuth? Czy jesteś świadomy potencjalnych ryzyk, które mogą powstać podczas implementacji procesu uwierzytelniania użytkownika? Przypomnijmy sobie krótko, co już wiemy na temat OAuth.

Simeng
Simeng
Developer

Wprowadzenie

O kilka dni temu natrafiłem na interesujący artykuł na temat podatności OAuth. A-new-oauth-vulnerability-that-may-impact-hundreds-of-online-services autorstwa SALT lab. Ten konkretny post podkreśla podatności odkryte w Expo, szeroko stosowanej ramce do implementacji OAuth i innych funkcjonalności. Konkretnie dotyczy to podatności w bibliotece expo-auth-session, która już została przydzielona i właściwie rozwiązana.

Jeśli interesujesz się OAuth lub pracujesz nad produktem związanym z CIAM jak my, zdecydowanie polecamy przeczytać ten artykuł. Jest dość inspirujący i dostarcza pomocnych wskazówek. Raporty white-hat przypominają nam, że nawet najprostsza funkcja może powodować podatności. Jeżeli chodzi o cyberbezpieczeństwo i autoryzację, nigdy nie można być zbyt ostrożnym w zabezpieczaniu prywatności i bezpieczeństwa informacji użytkownika. Jeśli ten artykuł przyciągnie Twoją uwagę, jestem przekonany, że zdecydowanie się z nami zgodzisz.

To przypomina mi czas, kiedy dopiero zaczynaliśmy. Spędziliśmy dużo czasu na uczeniu się i badaniu szczegółów protokołów OAuth i OIDC. Było to bolesne i monotonne, ale korzyści były ogromne. Chociaż być może nie każdy członek naszego zespołu jest ekspertem od OAuth, wszyscy są zaangażowani we wkładanie ciągłego wysiłku w bezpieczeństwo i staranność. Dzięki tym zaangażowanym wysiłkom produkt Logto rozwinął się do tego, co jest dzisiaj.

Dzięki tej wspaniałej okazji chcielibyśmy odświeżyć nasze wspomnienia na temat niektórych szczegółów związanych z bezpieczeństwem OAuth.

Podgląd przepływu autoryzacji OAuth Authorization Code Flow

OAuth 2.0 oferuje różne przepływy autoryzacji dostosowane do różnych typów klientów i wymagań. Wśród nich są Implicit Flow, Client Credentials Flow, Resource Owner Password Credentials Flow i Device Authorization Flow. Jednak Authorization Code Flow wyróżnia się jako najbezpieczniejszy i najczęściej używany. W przeciwieństwie do innych przepływów, oddziela on uwierzytelnianie użytkownika od aplikacji klienta i polega na wymianie kodu autoryzacyjnego na tokeny. Podejście to zapewnia dodatkową warstwę bezpieczeństwa, ponieważ wrażliwe tokeny nigdy nie są eksponowane na klienta. Ponadto, przepływ Authorization Code Flow obsługuje zarządzanie tokenami po stronie serwera, co sprawia, że jest odpowiedni dla aplikacji internetowych wymagających solidnego zabezpieczenia i zwiększonej kontroli nad dostępem użytkowników.

Poniżej znajduje się najprostszy schemat Authorization Code Flow:

Przyjrzyjmy się dwóm najważniejszym żądaniom wysyłanym w przepływie Authorization Code Grant i pozornie nieistotnym fragmentom w ich składzie, które odgrywają jednak kluczową rolę w ochronie przed oszustwem.

Punkt końcowy autoryzacji:

Punkt końcowy wymiany tokenów:

Poświadczenia klienta

W OAuth, Client Credentials odnoszą się do poświadczeń używanych przez aplikację klienta do uwierzytelnienia i identyfikacji się wobec serwera autoryzacyjnego. Te poświadczenia są otrzymywane podczas procesu rejestracji klienta i są używane do walidacji tożsamości klienta podczas wysyłania żądań do serwera autoryzacyjnego. (Możesz znaleźć swoje poświadczenia klienta w konsoli Admin Logto, gdy Twoja aplikacja jest po raz pierwszy rejestrowana. )

Poświadczenia klienta składają się zazwyczaj z dwóch komponentów:

  1. Client ID: Unikalny identyfikator przypisany do aplikacji klienta przez serwer autoryzacyjny. Jest to wartość publiczna, która zwykle nie jest uważana za wrażliwą.
  2. Client Secret: Poufna i bezpiecznie przechowywana wartość znana tylko klientowi i serwerowi autoryzacyjnemu. Służy jako forma uwierzytelniania dla aplikacji klienta i jest używana do weryfikacji tożsamości klienta podczas wysyłania żądań do serwera autoryzacyjnego.

Jak można zauważyć, kombinacja Client ID i Client Secret jest używana podczas żądania tokena do uwierzytelniania klienta i uzyskania tokenów dostępu.

Poświadczenia klienta odgrywają kluczową rolę w zapewnianiu bezpieczeństwa przepływu OAuth. Pomagają serwerowi autoryzacyjnemu weryfikować autentyczność aplikacji klienta i kontrolować dostęp do chronionych zasobów. Ważne jest, aby odpowiednio obsługiwać poświadczenia klienta i chronić je przed nieautoryzowanym dostępem. Logto kategoryzuje aplikacje klienta na dwa różne poziomy bezpieczeństwa:

  • Poufni klienci: Do nich należą aplikacje internetowe renderowane na serwerze oraz aplikacje machine-to-machine (M2M). W przypadku poufnych klientów wszystkie poświadczenia związane z autoryzacją, w tym poświadczenia klienta, są bezpiecznie przechowywane po stronie serwera. Dodatkowo wszystkie pośrednie żądania wymiany są szyfrowane, aby zapewnić poufność danych. Ryzyko wycieku poświadczeń klienta dla poufnych klientów jest bardzo niskie, co czyni je z natury bardziej bezpiecznymi. Dlatego poufni klienci są domyślnie traktowani z wyższym poziomem bezpieczeństwa.

  • Klienci publiczni: Do nich należą jednostronicowe aplikacje internetowe (SPA) i natywne aplikacje. W przypadku klientów publicznych poświadczenia klienta są zwykle twardo zakodowane po stronie klienta, na przykład w pakiecie JavaScript, lub w pakiecie aplikacji na natywnej platformie. Ryzyko wycieku poświadczeń jest wyższe w porównaniu do klientów poufnych ze względu na naturalne narażenie poświadczeń klienta w kodzie po stronie klienta.

State

W przepływie OAuth parametr state to losowo wygenerowana wartość, która jest dołączana do żądania autoryzacji wysyłanego przez klienta do serwera autoryzacyjnego. Jej celem jest utrzymanie stanu lub kontekstu żądania klienta w całym procesie autoryzacji.

Parametr state działa jako środek bezpieczeństwa zapobiegający atakom cross-site request forgery (CSRF). Kiedy serwer autoryzacyjny przekierowuje użytkownika z powrotem do aplikacji klienta po uwierzytelnieniu i autoryzacji, zawiera w odpowiedzi tę samą wartość stanu. Aplikacja klienta MUST porównuje tę wartość z oryginalną wartością state, którą wysłała w żądaniu autoryzacji.

Poprzez weryfikację parametru stanu, klient może upewnić się, że odpowiedź otrzymana od serwera autoryzacyjnego odpowiada początkowemu żądaniu, które złożył. Pomaga to zapobiegać atakom, w których napastnik próbuje oszukać klienta, aby ten zaakceptował odpowiedź przeznaczoną dla innego użytkownika lub aplikacji.

Let’s take a look at the original OAuth vulnerability report. (The following section is referenced from the original post)

When the user clicks “login with facebook” using the Mobile APP in Expo Go, it redirects to the user to the following link:

https://auth.expo.io/@moreisless3/me321/start?authUrl=https://www.facebook.com/v6.0/dialog/oauth?code_challenge=...&display=popup&auth_nonce=...&code_challenge_method=S256&redirect_uri=https://auth.expo.io/@moreisless3/me321&client_id=3287341734837076&response_type=code,token&state=gBpzi0quEg&scope=public_profile,email&returnUrl=exp://192.168.14.41:19000/--/expo-auth-session

In the response, auth.expo.io set the following cookie: _ru=exp://192.168.14.41:19000/--/expo-auth-session. The value RU will be later used as a Return Url in step 5. It then shows the user a confirmation message, and if the user approves - it redirects him to the Facebook login to continue the authentication flow

This page reads the query parameter “returnUrl” and sets the cookie accordingly.

Let’s change the returnUrl to hTTps://attacker.com (https is not allowed, so I tried to insert capitals letters and it worked), which sets the RU (Return Url)in the cookie to https://attacker.com.

In the above case, discard the original redirect_uri params, expos introduced a new param returnUrl without proper validation. This oversight provided opportunity for attackers to gain the access to Authorization Code returns by Facebook. For more details, please refer to the original post.

Redirect URI validation serves several important purposes:

  1. Preventing phishing attacks: By validating the Redirect URI, the authorization server ensures that the user is redirected back to a trusted and authorized endpoint. This helps prevent attackers from redirecting users to malicious or unauthorized locations.
  2. Protecting against open redirects: Open redirects are vulnerabilities that can be exploited to redirect users to malicious websites. By validating the Redirect URI, the authorization server can ensure that the redirect stays within the boundaries of the authorized domain, or set of trusted domains.
  3. Ensuring correct routing of authorization responses: Validating the Redirect URI helps guarantee that the authorization server redirects the user back to the intended client application. It ensures that the response – an Authorization Code or an Access Token, for example – is delivered to the correct destination.

In Logto, redirect_uri registration is mandatory for all types of applications. We compare and match the value received with the ones registered in the Logto server. This includes any custom query string parameters. If an authorization request fails validation process due to having a missing, invalid or mismatching redirect_uri value, an Invalid Redirect URI error will be returned back to the registered redirect_uri on file.

Summary

Due to its intricate and nuanced nature, it is understandable that these details are often overlooked. Some are just a simple string like state.

However, it is important to note these security measures add layers of security to user authorization, mitigating risks such as CSRF attacks, Authorization Code Interception, unauthorized redirections.

These are just a tiny piece of comprehensive security features OAuth protocol can offer. OAuth provides a robust framework for secure authentication and authorization. It also offers flexible and open-ended endpoints to cater various requirements in real-world product applications.

As developers and service providers, it is paramount to continuously prioritize the security of the user authorization flow. Staying vigilant, adhering to best practices, and keeping up with latest developments in the OAuth ecosystem are critical in ensuring the integrity and protection of user identities and sensitive data. We’ll remain committed in upholding the highest standards of security in the implementation of OAuth and safeguarding the privacy and trust of our users.