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

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-body o /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.
  1. Enumera i PID dei worker. Recupera /proc/<pid>/cmdline tramite LFI finché non trovi stringhe come nginx: worker process. Il numero di worker raramente supera il numero di CPU, quindi devi scansionare solo l’area bassa dello spazio PID.
  2. 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.
  3. 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 normalizzazioni realpath() 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.
  4. Includi per esecuzione. Quando colpisci il descriptor che punta ancora al body bufferizzato, una singola chiamata include o require esegue il tuo payload — nonostante il nome originale del file sia già stato unlinked. Se ti serve solo leggere il file, passa a readfile() 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’header Content-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 .so bufferizzato. 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 os

def 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>