LFI2RCE via fichiers temporaires de Nginx

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Configuration vulnérable

Example from bierbaumer.net a montrĂ© que mĂȘme la ligne suivante suffit lorsque PHP s’exĂ©cute derriĂšre un reverse proxy nginx qui met en tampon les corps de requĂȘte sur le disque :

<?php
$action = $_GET['action'] ?? 'read';
$path   = $_GET['file'] ?? 'index.php';
$action === 'read' ? readfile($path) : include $path;

Le cĂŽtĂ© nginx conserve gĂ©nĂ©ralement des chemins temporaires par dĂ©faut comme /var/lib/nginx/body et /var/lib/nginx/fastcgi. Quand un corps de requĂȘte ou une rĂ©ponse upstream dĂ©passe le tampon mĂ©moire (≈8 KB par dĂ©faut), nginx Ă©crit transparemment les donnĂ©es dans un fichier temporaire, garde le descripteur de fichier ouvert et ne supprime que l’entrĂ©e du nom de fichier. Tout include PHP qui suit des liens symboliques (comme /proc/<pid>/fd/<fd>) peut toujours exĂ©cuter le contenu non liĂ©, vous donnant RCE via LFI.

Pourquoi les fichiers temporaires nginx sont exploitables

  • Les corps de requĂȘte dĂ©passant le seuil du tampon sont vidĂ©s dans client_body_temp_path (par dĂ©faut /tmp/nginx/client-body ou /var/lib/nginx/body).
  • Le nom de fichier est alĂ©atoire, mais le descripteur de fichier reste accessible sous /proc/<nginx_pid>/fd/<fd>. Tant que le corps de la requĂȘte n’est pas complet (ou si vous maintenez le flux TCP en attente), nginx garde le descripteur ouvert mĂȘme si l’entrĂ©e de chemin a Ă©tĂ© supprimĂ©e.
  • Les include/require de PHP rĂ©solvent ces liens symboliques /proc/.../fd/..., donc un attaquant disposant d’une LFI peut parcourir procfs pour exĂ©cuter le fichier temporaire bufferisĂ© mĂȘme aprĂšs que nginx l’ait supprimĂ©.

Flux d’exploitation classique (rĂ©capitulatif)

  1. EnumĂ©rer les PIDs des workers. RĂ©cupĂ©rez /proc/<pid>/cmdline via la LFI jusqu’à trouver des chaĂźnes comme nginx: worker process. Le nombre de workers dĂ©passe rarement le nombre de CPU, vous n’avez donc qu’à scanner la plage basse des PIDs.
  2. Forcer nginx Ă  crĂ©er le fichier temporaire. Envoyez des corps POST/PUT trĂšs volumineux (ou des rĂ©ponses proxyĂ©es) afin que nginx Ă©crive dans /var/lib/nginx/body/XXXXXXXX. Assurez-vous que le backend ne lit jamais tout le corps — p.ex. maintenez le thread d’upload en keep-alive pour que nginx garde le descripteur ouvert.
  3. Mapper les descripteurs vers des fichiers. Avec la liste de PIDs, gĂ©nĂ©rez des chaĂźnes de traversal comme /proc/<pidA>/cwd/proc/<pidB>/root/proc/<pidC>/fd/<fd> pour contourner toute normalisation realpath() avant que PHP ne rĂ©solve la cible finale /proc/<victim_pid>/fd/<interesting_fd>. Le brute-force des descripteurs 10–45 suffit gĂ©nĂ©ralement car nginx rĂ©utilise cette plage pour les fichiers temporaires de body.
  4. Inclure pour exĂ©cution. Quand vous touchez le descripteur qui pointe encore vers le body bufferisĂ©, un seul include ou require exĂ©cute votre payload — mĂȘme si le nom de fichier original a dĂ©jĂ  Ă©tĂ© supprimĂ©. Si vous avez juste besoin de lire le fichier, utilisez readfile() pour exfiltrer le contenu temporaire au lieu de l’exĂ©cuter.

Variations modernes (2024–2025)

Ingress controllers et service meshes exposent dĂ©sormais souvent des instances nginx avec une surface d’attaque accrue. CVE-2025-1974 (“IngressNightmare”) est un bon exemple de l’évolution du trick classique des fichiers temporaires :

  • Les attaquants envoient un shared object malveillant comme corps de requĂȘte. Parce que le body >8 KB, nginx le bufferise dans /tmp/nginx/client-body/cfg-<random>. En mentant intentionnellement dans l’en-tĂȘte Content-Length (p.ex. dĂ©clarer 1 MB et ne jamais envoyer le dernier chunk) le fichier temporaire reste fixĂ© pendant ~60 secondes.
  • Le code de template vulnĂ©rable d’ingress-nginx permettait d’injecter des directives dans la config nginx gĂ©nĂ©rĂ©e. Combiner cela avec le fichier temporaire persistant rendait possible le brute-force des liens /proc/<pid>/fd/<fd> jusqu’à ce que l’attaquant dĂ©couvre le shared object bufferisĂ©.
  • L’injection de ssl_engine /proc/<pid>/fd/<fd>; forçait nginx Ă  charger le .so bufferisĂ©. Les constructeurs Ă  l’intĂ©rieur du shared object ont donnĂ© une RCE immĂ©diate dans le pod de l’ingress controller, qui a ensuite exposĂ© des secrets Kubernetes.

Un snippet de reconnaissance rĂ©duit pour ce type d’attaque ressemble Ă  :

Scanner procfs rapide ```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>

Exécutez-le depuis n'importe quel primitive (command injection, template injection, etc.) que vous possédez déjà. Renvoyez les chemins découverts `/proc/<pid>/fd/<fd>` dans votre paramÚtre LFI pour inclure le payload tamponné.

## Conseils pratiques

* Quand nginx dĂ©sactive le buffering (`proxy_request_buffering off`, `client_body_buffer_size` rĂ©glĂ© haut, ou `proxy_max_temp_file_size 0`), la technique devient beaucoup plus difficile — donc Ă©numĂ©rez toujours les fichiers de config et les en-tĂȘtes de rĂ©ponse pour vĂ©rifier si le buffering est encore activĂ©.
* Les hanging uploads sont bruyants mais efficaces. Utilisez plusieurs processes pour inonder les workers afin qu'au moins un temp file reste présent assez longtemps pour que votre LFI brute force le récupÚre.
* Dans Kubernetes ou d'autres orchestrators, les frontiĂšres de privilĂšges peuvent sembler diffĂ©rentes, mais le principe est le mĂȘme : trouvez un moyen de dĂ©poser des bytes dans les nginx buffers, puis parcourez `/proc` depuis n'importe oĂč oĂč vous pouvez effectuer des lectures sur le systĂšme de fichiers.

## 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/)

## Références

- [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]
> Apprenez et pratiquez le 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;">\
> Apprenez et pratiquez le 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;">
> Apprenez et pratiquez le 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>Soutenir HackTricks</summary>
>
> - Vérifiez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop) !
> - **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez-nous sur** **Twitter** 🐩 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Partagez des astuces de hacking en soumettant des PR au** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépÎts github.
>
> </details>