LFI2RCE via Nginx temp files
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Ευπαθής διαμόρφωση
Example from bierbaumer.net έδειξε ότι ακόμη και το παρακάτω one-liner είναι αρκετό όταν το PHP τρέχει πίσω από έναν nginx reverse proxy που αποθηκεύει προσωρινά τα σώματα των αιτήσεων στο δίσκο:
<?php
$action = $_GET['action'] ?? 'read';
$path = $_GET['file'] ?? 'index.php';
$action === 'read' ? readfile($path) : include $path;
The nginx side typically keeps default temp paths such as /var/lib/nginx/body and /var/lib/nginx/fastcgi. When a request body or upstream response is larger than the in-memory buffer (≈8 KB by default), nginx transparently writes the data to a temp file, keeps the file descriptor open, and only unlinks the file name. Any PHP include that follows symbolic links (like /proc/<pid>/fd/<fd>) can still execute the unlinked contents, giving you RCE through LFI.
Γιατί τα προσωρινά αρχεία του nginx μπορούν να καταχραστούν
- Τα σώματα αιτήματος που υπερβαίνουν το όριο του buffer εκχέονται στο
client_body_temp_path(προεπιλογή:/tmp/nginx/client-bodyή/var/lib/nginx/body). - Το όνομα του αρχείου είναι τυχαίο, αλλά το file descriptor παραμένει προσβάσιμο υπό
/proc/<nginx_pid>/fd/<fd>. Εφόσον το σώμα του αιτήματος δεν έχει ολοκληρωθεί (ή κρατάτε την TCP σύνδεση σε hanging), το nginx διατηρεί τον descriptor ανοιχτό ακόμη και αν η καταχώρηση διαδρομής έχει γίνει unlink. - Τα include/require του PHP επιλύουν αυτά τα
/proc/.../fd/...symlink, οπότε ένας επιτιθέμενος με LFI μπορεί να πηδήξει μέσα από procfs για να εκτελέσει το buffered προσωρινό αρχείο ακόμα και μετά το nginx το διαγράψει.
Κλασική ροή εκμετάλλευσης (ανακεφαλαίωση)
- Καταγράψτε τα worker PIDs. Πάρτε το
/proc/<pid>/cmdlineμέσω του LFI μέχρι να βρείτε συμβολοσειρές όπωςnginx: worker process. Ο αριθμός των workers σπάνια υπερβαίνει τους πυρήνες της CPU, οπότε χρειάζεται να σαρώσετε μόνο το κάτω μέρος του PID χώρου. - Εξαναγκάστε το nginx να δημιουργήσει το προσωρινό αρχείο. Στείλτε πολύ μεγάλα σώματα POST/PUT (ή proxied responses) ώστε το nginx να ξεχειλίσει στο
/var/lib/nginx/body/XXXXXXXX. Βεβαιωθείτε ότι το backend δεν διαβάζει ποτέ όλο το σώμα — π.χ. κρατήστε την upload σύνδεση σε keep-alive ώστε το nginx να διατηρεί τον descriptor ανοιχτό. - Αντιστοιχίστε τους descriptors με αρχεία. Με τη λίστα PID, δημιουργήστε αλυσίδες traversal όπως
/proc/<pidA>/cwd/proc/<pidB>/root/proc/<pidC>/fd/<fd>για να παρακάμψετε οποιαδήποτεrealpath()κανονικοποίηση πριν το PHP επιλύσει τον τελικό στόχο/proc/<victim_pid>/fd/<interesting_fd>. Το brute-forcing των file descriptors 10–45 συνήθως αρκεί επειδή το nginx επαναχρησιμοποιεί αυτό το εύρος για τα προσωρινά αρχεία σώματος. - Include για εκτέλεση. Όταν βρείτε τον descriptor που εξακολουθεί να δείχνει στο buffered σώμα, ένα μόνο
includeήrequireθα τρέξει το payload σας — ακόμα κι αν το αρχικό όνομα αρχείου έχει ήδη γίνει unlink. Αν χρειάζεστε μόνο ανάγνωση αρχείου, αλλάξτε σεreadfile()για να εξαγάγετε τα προσωρινά περιεχόμενα αντί να τα εκτελέσετε.
Σύγχρονες παραλλαγές (2024–2025)
Ingress controllers και service meshes πλέον ρουτίνας εκθέτουν instances του nginx με πρόσθετη επιφάνεια επίθεσης. CVE-2025-1974 (“IngressNightmare”) είναι ένα καλό παράδειγμα του πώς η κλασική τεχνική προσωρινών αρχείων εξελίσσεται:
- Επιτιθέμενοι σπρώχνουν ένα κακόβουλο shared object ως σώμα αιτήματος. Επειδή το σώμα είναι >8 KB, το nginx το bufferάρει στο
/tmp/nginx/client-body/cfg-<random>. Με το να ψεύδεστε σκόπιμα στην κεφαλίδαContent-Length(π.χ. δηλώνοντας 1 MB και μην στέλνοντας ποτέ το τελευταίο chunk) το προσωρινό αρχείο παραμένει pinned για ~60 δευτερόλεπτα. - Ο ευάλωτος template κώδικας του ingress-nginx επέτρεπε την έγχυση directives στο παραγόμενο nginx config. Συνδυάζοντας αυτό με το επίμονο προσωρινό αρχείο έκανε δυνατό το brute-force των
/proc/<pid>/fd/<fd>links μέχρι ο επιτιθέμενος να ανακαλύψει το buffered shared object. - Η εισαγωγή του
ssl_engine /proc/<pid>/fd/<fd>;ανάγκασε το nginx να φορτώσει το buffered.so. Οι constructors μέσα στο shared object παρείχαν άμεσο RCE μέσα στο ingress controller pod, το οποίο με τη σειρά του αποκάλυψε Kubernetes secrets.
Ένα συμπτυγμένο snippet αναγνώρισης για αυτό το στυλ επίθεσης μοιάζει με:
Γρήγορος σαρωτής 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>
Εκτέλεσέ το από οποιοδήποτε primitive (command injection, template injection, etc.) που ήδη έχεις. Τροφοδότησε τις ανακαλυφθείσες `/proc/<pid>/fd/<fd>` διαδρομές πίσω στην παράμετρο LFI για να συμπεριλάβεις το buffered payload.
## Πρακτικές συμβουλές
* Όταν το nginx απενεργοποιεί το buffering (`proxy_request_buffering off`, `client_body_buffer_size` ρυθμισμένο σε υψηλή τιμή, ή `proxy_max_temp_file_size 0`), η τεχνική γίνεται πολύ πιο δύσκολη — οπότε πάντα εξέτασε τα αρχεία διαμόρφωσης και τα response headers για να ελέγξεις αν το buffering παραμένει ενεργό.
* Τα "hanging" uploads είναι θορυβώδη αλλά αποτελεσματικά. Χρησιμοποίησε πολλαπλές διεργασίες για να κατακλύσεις τους workers, έτσι ώστε τουλάχιστον ένα προσωρινό αρχείο να παραμείνει αρκετό χρονικό διάστημα για να το πιάσει το LFI brute force σου.
* Σε Kubernetes ή άλλους orchestrators, τα όρια προνομίων μπορεί να φαίνονται διαφορετικά, αλλά το primitive είναι το ίδιο: βρες έναν τρόπο να ρίξεις bytes μέσα στους nginx buffers, και μετά περιηγήσου στο `/proc` από οπουδήποτε μπορείς να εκτελέσεις αναγνώσεις αρχείων.
## Εργαστήρια
- [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/)
## Αναφορές
- [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]
> Μάθετε & εξασκηθείτε στο AWS Hacking:<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;">\
> Μάθετε & εξασκηθείτε στο GCP Hacking: <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;">
> Μάθετε & εξασκηθείτε στο Azure Hacking: <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>Υποστηρίξτε το HackTricks</summary>
>
> - Ελέγξτε τα [**σχέδια συνδρομής**](https://github.com/sponsors/carlospolop)!
> - **Εγγραφείτε στην** 💬 [**ομάδα Discord**](https://discord.gg/hRep4RUj7f) ή στην [**ομάδα telegram**](https://t.me/peass) ή **ακολουθήστε** μας στο **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα** [**HackTricks**](https://github.com/carlospolop/hacktricks) και [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
>
> </details>


