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
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
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-bodyou/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)
- Enumérer les PIDs des workers. Récupérez
/proc/<pid>/cmdlinevia la LFI jusqu’à trouver des chaînes commenginx: worker process. Le nombre de workers dépasse rarement le nombre de CPU, vous n’avez donc qu’à scanner la plage basse des PIDs. - 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. - 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 normalisationrealpath()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. - Inclure pour exécution. Quand vous touchez le descripteur qui pointe encore vers le body bufferisé, un seul
includeourequireexé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, utilisezreadfile()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êteContent-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.sobufferisé. 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 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>
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>


