lunes, 21 de junio de 2010

Directory Transversal en descarga de Archivo

Me encontre con una web la cual nesesitaba descargar un fichero que me resultaba de interes, donde la direccion de descarga era similar a esto:
http://www.sitio.com/descarga/download.php?file=archivo.extension, por lo que me propuse verificar si dicho downloader tenia alguna validación, para provocar un Directory Transversal.
Lo que realize fue la peticion de este modo http://www.sitio.com/descarga/download.php?file=download.php, para descargarme el archivo download.php
y heureca :)



Al abrir el archivo download.php podemos empezar a verificar las fallas de la validaciones:


$filename = $_GET['file'];

// addition by Jorg Weske
$file_extension = strtolower(substr(strrchr($filename,"."),1));

if ( ! file_exists( $filename ) )
{
echo "not file";
exit;
};
switch( $file_extension )
{
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";

header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers
header("Content-Type: $ctype");
// change, added quotes to allow spaces in filenames, by Rajkumar Singh
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
readfile("$filename");


?>


en la primera linea, podemos ver que toma el nombre del archivo por la variable $_GET['file'] y lo guarda en $filename, luego en la linea 4 lo que hace esta funcion es tomar todo el nombre del archivo y solo obtener su extension por ejemplo, si el archivo a descargar es archivo.pdf la variable $file_extension va a contener pdf, aca fue lo que me parecio algo muy bueno cuando estaba leyendo el codigo, pero solo lo usa para colocar el tipo de MIME(linea 12), lo cual esta muy bien pero tambien ubiera filtrado con ellos una black-list para que no se pueda descargar entensiones peligrosas.
En la linea 31 mostramos el nombre del archivo que le aparecera al usuario cuadno descarga y en la linea 33 el Content-Lenght es el tamaño del archivo, ah y la linea 29 es el MIME del que hablamos anteriormente. :)
Como la descarga se realizo con un php podemos llegar a pensar que podemos descargar cualquier php de la web, entonces buscaremos descargar el index que es donde puede haber datos interesantes de conexion de base de datos :)

http://www.sitio.com/descarga/download.php?file=../index.php



Al abrir el archivo index.php vemos esta informacion un poco mas interesante que la anterior



Nos descargamos el archivo class_DB.php, y dentro de ese archivo vemos una linea mucho mas interesante


include("conectar.php");


Y como piensan que sigue esto? ........... Si correcto, nos descargamos el archivo conectar.php




Bien ahora queda buscar el phpmyadmin, colocando www.sitio.com/phpmyadmin de la forma facil, y si no encontramos ahi podemos largar algun bruteador. O tambien que es la que mas me gusta por el cliente de mysql, primero comprobamos si el puerto esta abierto hacia el publico con Nmap :)



y ahora nos conectamos




Creo que queda entendida la peligrosidad de lo que se expone a no validar estas entradas asi como todas las entradas que se le da al usuario, siempre hay que verificarlas. Desde una simple bajada de archivo pudimos ingresar a sus datos, romper la confidencialidad de ellos, podriamos romper su integridad y hasta la disponibilidad de su sitio Web.

Para completar, al mismo script, le coloque seguridad, para que no se pueda descargar alguna extension peligrosa como php, asp, inc, etc. y para que no se pueda escalar directorios.



$index="http://".$_SERVER['SERVER_NAME']."/index.php";
$filename = basename($_GET['file']);
$ruta="descargas/".$filename;
// addition by Jorg Weske
$file_extension = strtolower(substr(strrchr($filename,"."),1));
#------------Bloque Seguridad ------------------
if(preg_match('/(php|asp|ini|inc|bak)/',$file_extension)){
header("Location:".$index);
}

elseif( $filename == "" )
{
header("Location:".$index);
}
elseif( ! file_exists( $ruta ) )
{
header("Location:".$index);
};

#-----------Fin Bloque Seguridad--------------
switch($file_extension )
{
case "pdf": $ctype="application/pdf"; break;
case "exe": $ctype="application/octet-stream"; break;
case "zip": $ctype="application/zip"; break;
case "doc": $ctype="application/msword"; break;
case "xls": $ctype="application/vnd.ms-excel"; break;
case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpg"; break;
default: $ctype="application/force-download";
}

header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".$filename."\";" );#nombre del archivo en la descarga
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($ruta));
readfile("$ruta");



?>


La segunda linea usamos la funciona basename, que logra que si el usuario coloca por ejemplo /carpeta/carpeta2/archivo.pdf, nos devilvera archivo.pdf, eliminado toda la ruta anterior y con la ayuda de la linea 3 ponemos una carpeta llamada descargas, la cual en ella contendra todos los archivos para descargas (valga la redundancia), y donde el usuario nunca podra escaparse de ella.
Asi por ejemplo si el usuario intenta descargar de esta forma
www.sitio.com.ar/download.php?file=/etc/passwd la variable $filename quedara con el valor passwd, y concatenando con la carpeta descargas la variable $ruta contendra descargas/passwd
En el bloque de seguridad, la primer linea verifica con una expresion regular que si existe esas extensiones, te direcciones al index (se puede colocar tantas como guste en esa lista).


Eso es todo

Saludos

miércoles, 16 de junio de 2010

Seguridad en Apache




Bueno hace mucho que no andaba haciendo nada por el blog, por motivos de la facultad y otras cuestiones personales :).
Tengo que dar una clase en la Facultad Fa.C.E.N.A, en la catedra Redes de Altas Prestaciones en la cual soy adscripto, y como tema elegi Apache.
Bueno la documentación en si no esta muy avanzada ya que seria mas que nada una introduccion a lo que es apache y como configurarlo apuntando a la seguridad en un nivel intermedio, por motivos de que solamente lo doy en una sola expocición y hay alumnos que nunca instalarón Apache, ni mucho menos tocaron Linux asi que uno de mis objetivos es que se codeen con Debian y obviamte configurar Apache que es el eje de la clase.
Tambien trabajo con Lampp, por cuestiones de que esta catedra esta en el ultimo año y ya estamos todos con el tema de la Tesis, y algunos estan tirando hacia PHP, y este paquete nos trae todo empaquetado MySQL, PHP y Apache, aunque lo mejor hubiera sido compilarlo a Apache desde 0 descargando de la pagina oficial.
Bueno la información que elegi creo que esta buena para empezar a toquetear las funcionalidades basicas y no tan basicas de Apache, les dejo mas abajo el material.





Enlace






Saludos a todos y Feliz Dia del Padre :)