viernes, 29 de marzo de 2019

Arbitrary File Download: el hermano menor del LFI.

¡Hola, muy buenas!

En esta ocasión les vengo a comentar sobre una vulnerabilidad a nivel web bastante frecuente, y a su vez, poco conocida. Se denomina Arbitrary File Download, y de ahora en más, AFD.

(fig 1. Arbitrary File Download).
A menudo es una vulnerabilidad que se confunde con la ya conocida Local File Inclusion, o LFI. Estás perdonado si alguna vez las confundiste, pues las similitudes que tiene son casi todas, a excepción de la metodología de trabajo. En esta entrada, me dispongo a intentar solventar todas las dudas que pueda existir sobre la diferencia de ambas vulnerabilidades.

Apéndice I: El código en PHP

Para entender más claramente las diferencias, analizaremos los códigos PHP vulnerables utilizados en ambas vulnerabilidades.

  1. <?php
  2. include($_GET['page']);
  3. // Otras funciones: include_once(), require(), require_once().
  4. ?>
(Código 1. Local File Inclusion).

Es posible combinar LFI con técnicas como Log poisoning, /proc/self/environ, phpinfo(), etc. para conseguir RCE en el servidor.


  1. <?php
  2. $file = $_GET['file'];
  3. header('Content-Type: application/octet-stream');
  4. header('Content-Disposition: attachment; filename="' .basename($file) .'"');
  5. header('Content-Length: ' . filesize($file));
  6. readfile($file);
  7. ?>
(Código 2. Arbitrary File Download).

El uso de readfile() es utilizado a lo largo de muchas páginas web para las secciones de "descarga de contenido". Esto significa que un único archivo php (llámese download.php) es el encargado de descargar los ficheros del servidor.

Apéndice II: Post-análisis del código

Luego de analizar ambos códigos, llegamos a la conclusión de que LFI permite incluir ficheros locales del servidor, y en cambio, AFD permite descargar esos ficheros.
La gran diferencia entre ambas vulnerabilidades, es que AFD no permite obtener RCE mediante técnicas como log poisoning o /proc/self/environ.

Si, muchos dirán "si es menos útil que LFI, ¿para qué la quiero?". LFI es una vulnerabilidad que poco a poco se hizo conocida y los desarrolladores tienen especial cuidado con ella. En cambio, AFD es una vulnerabilidad muy "precaría" aún, y es usual encontrarla en 7 de cada 10 sitios (vamos, que un sencillo dork en Google da toda la información).

Apéndice III: Usos de AFD

Sin menospreciar a AFD, a continuación daré una lista de usos posibles que se me han ocurrido. Todos ellos intentan garantizar conseguir una shell en el servidor victima.

  • Leer archivos de configuración MySQL. Si la página web cuenta con algún panel de administrador MySQL (phpMyAdmin, Adminer, phpLitleAdmin, etc.), es posible loguearse a dicho panel y subir un archivo a través de consultas MySQL.
  • Desde el mismo phpMyAdmin, listar los usuarios admin y sus contraseñas de un panel admin, así conseguir acceso a dicho panel, que tal vez contenga algún Unrestricted File Upload.
  • A veces, el servidor MySQL es remoto, pudiendo conectarse desde cualquier cliente MySQL. Por ejemplo, phpMyAdmin.co.
  • Leer archivos de sesión PHP. Alguna de esas sesiones, de seguro será admin.
  • Contraseñas admin hardcodeadas en el login. Es poco frecuente, pero sorprendente de cuantos programadores hardcodean las contraseñas.
  • Mucho más... Los límites son tu imaginación.
 

 Apéndice IV: Análisis final

En conclusión podemos decir que AFD tiene "más limitaciones" que LFI, pero a su vez es más frecuente, lo que lo convierte en una vulnerabilidad importante. Ambas técnicas necesitan ser combinadas con otras para conseguir un resultado útil.

Hago una pausa aquí para aclarar una cosilla. Si no lo han descubierto aún, LFI no permite leer el contenido de archivos PHP (al menos no es posible sin utilizar otra técnica, /proc/...), en cambio, AFD si permite leer el contenido de esos ficheros.

En esta parte de la entrada pensé en listar una serie de "soluciones" a esta vulnerabilidad, pero confío en la mente del lector perspicaz y ágil que logrará resolverlo por si mismo. Recuerdo una frase muy importante: Never trust the user input.

Apéndice V: Ejemplo práctico

Como toda buena entrada sobre hacking y vulnerabilidades, hay que finalizar poniendo en práctica lo recién aprendido. En este apéndice me centraré en conseguir acceso a una página web aleatoría (si, Google Dorking), utilizando AFD y en combinación de otras técnicas.

Evitaré sacar capturas de los pasos innecesarios, pero aún así los listaré:

  1. Conseguir leer el archivo "index.php", usualmente tiene mucha información útil. En este caso, tenía un require() a un archivo "mysql.inc.php"
(fig 2. Fichero mysql.inc.php).

Logré leer el fichero de conexión MySQL, el cual contaba con la información confidencial que requería. En este caso no vemos información sobre el servidor MySQL, por lo cual podemos deducir que se trata de un localhost.

Mi siguiente paso fue intentar conseguir algún tipo de panel MySQL, para darle uso a los datos recién conseguidos.








(fig 3. Ingreso phpMyAdmin).


Afortunadamente la página web contaba con un panel phpMyAdmin en un subdominio (phpmyadmin.domain.tld), siendo posible el ingreso con los datos anteriormente obtenidos.






(fig 4. Datos administrativos).

 Al buscar entre todas las tablas, llegué a la que me interesaba a mi. El siguiente paso era claro: obtener el URL del panel admin. Afortunadamente a muchos programadores se les da por dejarle como /admin, o simplemente dejarlo en robots.txt.


(fig 5. Panel administrativo).

 ¡Y voilà! Ya hemos accedido al panel administrativo. Si mis intenciones fuesen malas, buscaría algún uploader y subiría una shell, pero como prueba de concepto, creo que debería detenerme aquí.







  

Hasta aquí la entrada de hoy. Empezaré a publicar contenido más seguido.😁😁😁

Be happy and never (never) trust the user input ;-)
Nobody.

Pssst: Recuerda seguirme en Twitter :-): https://twitter.com/n0bodysec

No hay comentarios: