Azure Skeleton Key: az áthaladó hitelesítés kihasználása hitelesítő adatok ellopására

szerkesztés: Adam Chester biztonsági kutató korábban írt az Azure AD Connect For Red Teamers – ről, a hitelesítési funkció összekapcsolásáról. Nézd meg a félelmetes írás itt.

Összefoglalás

ha egy támadó veszélyezteti egy szervezet Azure agent kiszolgálóját–amely az Azure AD és az on-prem AD szinkronizálásához szükséges összetevő–, akkor létrehozhat egy hátsó ajtót, amely lehetővé teszi számukra, hogy bármely szinkronizált felhasználóként bejelentkezzenek. Létrehoztunk egy proof-of-concept, amely manipulálja az Azure hitelesítési funkció 1.) adjon meg nekünk egy álkulcs jelszót, amely minden felhasználó számára működik, és 2.) dump minden valós egyértelmű szöveges felhasználónevek és jelszavak egy fájlba.

átmenő hitelesítés az Azure AD-Connect használatával

Azure AD-Connect Azure AD-környezetet egy helyszíni tartományhoz köti, és számos hitelesítési módszert biztosít:

  • jelszó Hash szinkronizálás-egy módszer, amely szinkronizálja a helyi on-prem hash a felhő.
  • átmenő hitelesítés-olyan módszer, amely “Azure agent” – et telepít a prem-re, amely hitelesíti a felhőből szinkronizált felhasználókat.
  • összevonás – olyan módszer, amely egy AD FS infrastruktúrára támaszkodik.

támadási módszerünk kihasználja az átmenő hitelesítéshez használt Azure-ügynököt. Az on-prem ügynök összegyűjti és ellenőrzi az Azure AD által az on-prem tartományokkal szinkronizált fiókok hitelesítő adatait.

a hitelesítési folyamat

 Azure átmenő hitelesítési folyamat

  1. a felhasználó beírja felhasználónevét és jelszavát az Azure AD/O365-be.
  2. az Azure AD egy nyilvános kulcs segítségével titkosítja a hitelesítő adatokat, és az ügynöksorba helyezi őket – ez egy állandó kapcsolat, amelyet az on-prem ügynök hoz létre. Az ügynök ezután összegyűjti a hitelesítő adatokat, és visszafejti őket a privát kulcsával.
  3. ezután az ügynök a LogonUserW API függvény segítségével hitelesíti a felhasználót az on-Prem DC-re.
  4. a DC ellenőrzi a hitelesítő adatokat, és választ ad vissza.
  5. az on-prem DC válasza visszakerül az Azure AD-be.
  6. ha a felhasználó bejelentkezése sikeres, a felhasználó be lesz jelentkezve.

az ügynök visszaélése

az ügynök kihasználásához a következőkre lesz szükségünk:

  • az Azure AD Connect az átmenő hitelesítésre van konfigurálva.
  • rendszergazdai jogosultságok olyan kiszolgálón, amelyen Azure-ügynök van telepítve.

miután kompromittáltunk egy Azure-ügynököt futtató kiszolgálót, megváltoztathatjuk a hitelesítési folyamatot. A hitelesítő adatok ellenőrzéséért felelős folyamatot kényelmesen azureadconnectauthenticationagentservice-nek hívják.az EXE és a LogonUserW API függvényre támaszkodik. A Microsoft dokumentációja kimondja: “a Hitelesítési ügynök megpróbálja érvényesíteni a felhasználónevet és a jelszót az intézményi Active Directory ellen a Win32 LogonUser API használatával, a dwLogonType paraméter LOGON32_LOGON_NETWORK értékre állítva.

ha az API-hívást az APIMonitor segítségével kapcsoljuk be (olyan eszköz, amely bármilyen Windows API-hívást összekapcsolhat, feltételezve, hogy rendszergazdai jogosultságokkal rendelkezik), akkor érdekes dolgokat kezdhetünk el nézni a hitelesítési folyamat során:

API Monitor

a felhasználó “noob” hitelesített jelszóval “mypassword”.

 Azure Agent veszélyben (Ralph Wiggum meme)

API Monitor létrehozása

most, hogy tudjuk, hogyan lehet hozzáférni a jelszavakhoz, nézzük meg, automatizálhatjuk-e a folyamatot.

a terv egy DLL befecskendezése az AzureADConnectAuthenticationAgentservice-be.írja át a mutatót a LogonUserW függvényre a saját funkciónkkal.

az EasyHook használatával írtunk egy DLL-t, amely összekapcsolja a LogonUserW függvényt, és lecseréli egy új LogonUserW-re:

BOOL myLogonUserW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken){ //Write to file ofstream myfile; myfile.open("c:\temp\shhhh.txt", std::ios_base::app); string user = utf8_encode(lpszUsername); string pass = utf8_encode(lpszPassword);myfile << "Username: "; myfile << user << "\n"; myfile << "Password: "; myfile << pass << "\n\n"; myfile.close(); return LogonUserW(lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken);}

vegye figyelembe, hogy a funkció ugyanannyi paramétert igényel, mint a LogonUserW. A függvény meghívásakor létrehozza a ” shhhh.txt ” és írja be a felhasználónév és jelszó változókat. A függvény a valódi LogonUserW hívás eredményét adja vissza az eredetileg megadott paraméterekkel.

a DLL befecskendezése

az InjectAllTheThings és a fényvisszaverő DLL moduljának köszönhetően betöltöttük a DLL-t a folyamatba, és a következő eredményeket kaptuk:

egyértelmű szöveges jelszavak

minden szinkronizált felhasználó, aki csatlakozik az Azure AD-hez (például Office 365), hozzáadja a jelszavát a szöveges fájlunkhoz.

La Cerise sur le G Main Distincteau

jelszógyűjtőnknek csak egy kis “nem tudom mit” kell ahhoz, hogy Azure álkulcs legyen, amely lehetővé teszi a támadó számára, hogy (egy tényezővel) hitelesítsen, mint bármely felhasználó, előre meghatározott jelszó használatával.

álkulcsunk esetében módosítjuk a visszatérési értéket a LogonUserW függvényben, így amikor megadjuk a ‘feltört’ jelszót, sikeresen bejelentkezünk, függetlenül a felhasználó valódi jelszavától. LogonUserW egy logikai függvény, amely kap egy mutatót a felhasználó token, feltölti azt egy felhasználói token és visszatér igaz, ha sikeres.

egy kis tesztelés azt mutatja, hogy a hamis token vagy a token nélküli visszaadás a folyamat összeomlását okozza, ezért a programnak érvényes Tokenre van szüksége.

hol kaphatunk egy felhasználói tokent a függvényhez anélkül, hogy létrehoznánk egyet?

Nos, mivel már az AzureADConnectAuthenticationAgentservice-ben vagyunk.exe folyamat, kölcsönözhetjük a felhasználói tokent!

új verzió:

BOOL myLogonUserW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken){ //Write to file ofstream myfile; myfile.open("c:\temp\beep.txt", std::ios_base::app); string user = utf8_encode(lpszUsername); string pass = utf8_encode(lpszPassword); //get time std::time_t result = std::time(nullptr); myfile << " "; myfile << std::asctime(std::localtime(&result)); myfile << "Username: "; myfile << user << "\n"; myfile << "Password: "; myfile << pass << "\n\n"; myfile.close(); string hacked = "hacked"; if(hacked.compare(pass)) { // Log the user in return LogonUserW(lpszUsername, lpszDomain, lpszPassword, dwLogonType, dwLogonProvider, phToken); } else { // Use Skeleton Key, return true OpenProcessToken(GetCurrentProcess(), TOKEN_READ, phToken); return true; }}

az OpenProcessToken meghívásával feltöltjük a phToken változót a folyamat saját tokenjével.

működik, mint egy varázsa!

bár minden felhasználó továbbra is csatlakozhat a saját jelszavával, sikeresen hitelesíthetjük, mint bármely Felhasználó a “feltört”jelszó használatával.

tessék …

ekkor a támadó teljes és teljes ellenőrzést szerzett a bérlő felett, és bármely felhasználóként bejelentkezhet, beleértve a globális rendszergazdai fiókot is. Ez a Végjáték.

záró gondolatok

álkulcs telepítése az Azure-ügynökökre hasznos lehet:

  • a jogosultságok kiterjesztése a globális rendszergazdára (ami viszont lehetővé teszi az Azure-bérlő vezérlését)
  • hozzáférés a szervezet on-prem környezetéhez a tartományi rendszergazdai jelszó visszaállításával (feltételezve, hogy a jelszó visszaírása engedélyezve van)
  • a perzisztencia fenntartása egy szervezetben
  • cleartext jelszavak gyűjtése

a Microsoft Security Response Center jelentésre adott válasza arra enged következtetni, hogy nem jön létre javítás:

úgy tűnik, hogy ez a jelentés nem azonosítja a Microsoft-termék vagy-szolgáltatás olyan gyengeségét, amely lehetővé tenné a támadó számára, hogy veszélyeztesse a Microsoft-ajánlat integritását, elérhetőségét vagy bizalmas jellegét. Ebben a kérdésben a támadónak először veszélyeztetnie kell a gépet, mielőtt átveheti a szolgáltatást.

bár nem ismerem az Azure átmenő hitelesítésének belső működését, javasolhatok néhány megoldást, amelyek segíthetnek enyhíteni ezt a biztonsági rést. Lehetséges például a titkosított hitelesítő adatok továbbítása az ügynöktől egy központosított ügynöknek, amely a DC-n (általában egy jól védett kiszolgálón) található. Ez a DC-ügynök ellenőrzi a hitelesítő adatokat, és titkosított választ ad, amelyet csak az Azure felhőszolgáltatása nyithat meg. Az a támadó, aki teljes irányítást szerzett egy DC-n, már nyert, az ebből következő kihasználásokat beárnyékolja ez a tény.

az egyik ügyfelünk volt egy igazán érdekes veszi ezt is:

az álkulcs problémát jelenthet olyan környezetekben, amelyek lehetővé teszik a felhasználó számára, hogy MFA nélkül jelentkezzen be az Azure/O365 fiókokba, de az ügynök képes minden egyes bejelentkezési azonosítót és jelszót egyszerű szövegben rögzíteni, amikor az Azure hitelesíti a helyi DC-t. Ez a támadó számára érvényes felhasználói fiókok tömegét biztosítaná, amelyek felhasználhatók az on-prem erőforrásokba való bejelentkezéshez különböző felhasználókként. Hirtelen a kiszolgáló rendszergazdája, akinek nem volt hozzáférése az adatbázisokhoz, más eszközökhöz és erőforrásokhoz, most elegendő felhasználói fiókkal rendelkezik ahhoz, hogy bejárja az egész helyet, és hozzáférjen olyan adatbázisokhoz, amelyek korábban nem rendelkeztek. Igen, azzal érvelhet, hogy megragadja a hirdetést .dit fájl is ezt, de ezek a jelszavak még hash, akkor kell extra időt, hogy akár kiváló a hash offline, vagy használja a pass a hash típusú támadás (amelyek közül sok lenne kimutatható). Ez az új módszer sokkal könnyebbnek tűnik a fenyegetés szereplői számára, és nehezebb az infravörös csapat számára.

megelőzés

a privilegizált támadók ezt a kihasználást hátsó ajtó telepítésére vagy jelszavak gyűjtésére használhatják. A hagyományos naplóelemzés ezt nem tudja észlelni, ha a támadó tudja, hogyan takarja el a nyomait.

az MFA használata megakadályozza, hogy a támadók hamis jelszóval csatlakozzanak az Azure-felhőhöz, bár ez a támadás felhasználható jelszavak gyűjtésére az MFA-kompatibilis környezetekben.

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.