LFI2RCE via Nginx temp files
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Configurazione vulnerabile
Example from bierbaumer.net ha mostrato che anche la seguente one-liner è sufficiente quando PHP viene eseguito dietro un nginx reverse proxy che memorizza su disco i corpi delle richieste:
<?php
$action = $_GET['action'] ?? 'read';
$path = $_GET['file'] ?? 'index.php';
$action === 'read' ? readfile($path) : include $path;
Il lato nginx tipicamente mantiene percorsi temporanei predefiniti come /var/lib/nginx/body e /var/lib/nginx/fastcgi. Quando un body di richiesta o una risposta upstream è più grande del buffer in memoria (≈8 KB di default), nginx scrive trasparentemente i dati in un file temporaneo, mantiene aperto il file descriptor e rimuove solo il nome del file. Qualsiasi PHP include che risolve link simbolici (come /proc/<pid>/fd/<fd>) può comunque eseguire il contenuto unlinkato, permettendoti RCE tramite LFI.
Perché i file temporanei di nginx possono essere sfruttati
- I body delle richieste che superano la soglia del buffer vengono scaricati in client_body_temp_path (di default
/tmp/nginx/client-bodyo/var/lib/nginx/body). - Il nome del file è casuale, ma il file descriptor resta raggiungibile sotto
/proc/<nginx_pid>/fd/<fd>. Finché il body della richiesta non è completato (o mantieni il flusso TCP sospeso), nginx mantiene il descriptor aperto anche se la voce del percorso è stata rimossa (unlinked). - Gli include/require di PHP risolvono quei symlink
/proc/.../fd/..., quindi un attaccante con LFI può attraversare procfs per eseguire il file temporaneo ancora bufferizzato anche dopo che nginx lo ha cancellato.
Flusso di sfruttamento classico (riepilogo)
- Enumera i PID dei worker. Recupera
/proc/<pid>/cmdlinetramite LFI finché non trovi stringhe comenginx: worker process. Il numero di worker raramente supera il numero di CPU, quindi devi scansionare solo l’area bassa dello spazio PID. - Forza nginx a creare il file temporaneo. Invia body POST/PUT molto grandi (o risposte proxate) in modo che nginx riversi su
/var/lib/nginx/body/XXXXXXXX. Assicurati che il backend non legga mai l’intero body — per esempio, mantieni la connessione di upload aperta (keep-alive) così nginx mantiene il descriptor aperto. - Mappa i descriptor ai file. Con la lista dei PID, genera catene di traversal come
/proc/<pidA>/cwd/proc/<pidB>/root/proc/<pidC>/fd/<fd>per bypassare eventuali normalizzazionirealpath()prima che PHP risolva il target finale/proc/<victim_pid>/fd/<interesting_fd>. Fare brute-force sui file descriptor 10–45 è solitamente sufficiente perché nginx riusa quel range per i file temporanei dei body. - Includi per esecuzione. Quando colpisci il descriptor che punta ancora al body bufferizzato, una singola chiamata
includeorequireesegue il tuo payload — nonostante il nome originale del file sia già stato unlinked. Se ti serve solo leggere il file, passa areadfile()per esfiltrare il contenuto temporaneo invece di eseguirlo.
Variazioni moderne (2024–2025)
Ingress controller e service mesh ora espongono di routine istanze nginx con una superficie di attacco aggiuntiva. CVE-2025-1974 (“IngressNightmare”) è un buon esempio di come il trucco classico dei file temporanei si evolve:
- Gli attaccanti inviano un oggetto shared malevolo come body della richiesta. Poiché il body è >8 KB, nginx lo bufferizza in
/tmp/nginx/client-body/cfg-<random>. Mentendo intenzionalmente nell’headerContent-Length(es. dichiarando 1 MB e non inviando mai l’ultimo chunk) il file temporaneo rimane pinned per ~60 secondi. - Il codice del template vulnerabile di ingress-nginx permetteva di iniettare direttive nella config nginx generata. Combinato con il file temporaneo persistente, questo rendeva possibile fare brute-force sui link
/proc/<pid>/fd/<fd>finché l’attaccante non scopriva l’oggetto shared bufferizzato. - L’iniezione di
ssl_engine /proc/<pid>/fd/<fd>;costringeva nginx a caricare il.sobufferizzato. I constructor all’interno dell’oggetto shared fornivano RCE immediata nel pod dell’ingress controller, che a sua volta esponeva i Kubernetes secrets.
Uno snippet di ricognizione ridotto per questo tipo di attacco assomiglia a:
Scanner rapido di procfs
```python #!/usr/bin/env python3 import osdef find_tempfds(pid_range=range(100, 4000), fd_range=range(10, 80)): for pid in pid_range: fd_dir = f“/proc/{pid}/fd“ if not os.path.isdir(fd_dir): continue for fd in fd_range: try: path = os.readlink(f“{fd_dir}/{fd}“) if “client-body” in path or “nginx” in path: yield pid, fd, path except OSError: continue
for pid, fd, path in find_tempfds(): print(f“use ?file=/proc/{pid}/fd/{fd} # {path}“)
</details>
Esegui questo da qualsiasi primitive (command injection, template injection, ecc.) che hai già. Fornisci i percorsi scoperti `/proc/<pid>/fd/<fd>` al parametro LFI per includere il payload presente nel buffer.
## Suggerimenti pratici
* Quando nginx disabilita il buffering (`proxy_request_buffering off`, `client_body_buffer_size` tuned high, or `proxy_max_temp_file_size 0`), la tecnica diventa molto più difficile — quindi enumera sempre i file di configurazione e gli header di risposta per verificare se il buffering è ancora abilitato.
* Gli upload appesi sono rumorosi ma efficaci. Usa più processi per sovraccaricare i worker in modo che almeno un file temporaneo rimanga abbastanza a lungo perché la tua brute force LFI lo catturi.
* In Kubernetes o altri orchestratori, i confini di privilegio possono apparire diversi, ma la primitive è la stessa: trova un modo per inserire byte nei buffer di nginx, poi esplora `/proc` da qualsiasi posizione in cui puoi effettuare letture del file system.
## Labs
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/php-lfi-with-nginx-assistance.tar.xz)
- [https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/](https://2021.ctf.link/internal/challenge/ed0208cd-f91a-4260-912f-97733e8990fd/)
- [https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/](https://2021.ctf.link/internal/challenge/a67e2921-e09a-4bfa-8e7e-11c51ac5ee32/)
## Riferimenti
- [https://bierbaumer.net/security/php-lfi-with-nginx-assistance/](https://bierbaumer.net/security/php-lfi-with-nginx-assistance/)
- [https://www.opswat.com/blog/ingressnightmare-cve-2025-1974-remote-code-execution-vulnerability-remediation](https://www.opswat.com/blog/ingressnightmare-cve-2025-1974-remote-code-execution-vulnerability-remediation)
> [!TIP]
> Impara e pratica il hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Impara e pratica il hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Impara e pratica il hacking Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Supporta HackTricks</summary>
>
> - Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
> - **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos github.
>
> </details>


