Leer htaccess a través de Blind SQL injection

En esta ocasión me gustaría hablar de uno de los retos que solucioné hace poco y que encontré bastante interesante. En éste, debíamos conseguir acceder a la zona privada de una página web protegida con htaccess que contenía un blind SQL injection (vulnerabilidad ampliamente conocida, pero si alguien no la conoce, en Internet hay multitud de información, como por ejemplo https://www.owasp.org/index.php/Blind_SQL_Injection).

En MySQL disponemos de la función load_file, la cual nos permite acceder a un fichero siempre y cuando tengamos el privilegio FILE. Así que lo primero que debemos hacer es comprobar los permisos del usuario con que se están ejecutando las consultas.

Antes de continuar, me gustaría aclarar que todas las consultas se pueden hacer de forma manual, o con scripts realizados por uno mismo, pero hay veces que existen herramientas que nos facilitan mucho la tarea y se puede obtener el mismo resultado mucho más rápido. Como por ejemplo con sqlmap (http://sqlmap.org/), que sirve para explotar vulnerabilidades SQL injection.

Sqlmap dispone de la opción --privileges que nos da automáticamente los privilegios que tiene el usuario que realiza las consultas en el servidor. Así que con una consulta como la siguiente podríamos ver si disponemos de los privilegios necesarios:

./sqlmap.py -u "http://web.vulnerable" --data="post_data" -p variable_vulnerable
   --string="string_que_se_muestra_cuando_TRUE" --privileges

(La instrucción anterior es un simple ejemplo, ya que en algunas ocasiones tenemos que jugar con las diferentes opciones de sqlmap (como por ejemplo --prefix o --postfix/suffix) para poder automatizar el proceso y explotar la vulnerabilidad como nosotros queremos.

Viendo que el usuario dispone de permisos FILE, sabemos que podemos leer ficheros del sistema, pero el problema es que aún no sabemos dónde se encuentra nuestro fichero .htaccess.

En el archivo de configuración de apache, podemos encontrar DocumentRoot, variable que indica el path donse se encuentra la página web en el sistema. Por lo tanto, primero debemos encontrar este fichero. En el siguiente enlace podemos encontrar algunos posibles paths para el fichero en cuestión: http://wiki.apache.org/httpd/DistrosDefaultLayout según el sistema operativo.

Para ver si un archivo existe (o tenemos acceso a él) se puede hacer utilizando una instrucción como la siguiente:

and !isnull(load_file(0x<path_fichero_en_hexadecimal>))

Donde el resultado final de la sentencia será verdadero si tenemos acceso al fichero o falso si no lo tenemos.

En este reto en concreto veíamos que no teníamos acceso a ningún fichero probado del sistema (/etc/passwd tampoco), así que analizando MySQL descubrí la variable secure_file_priv, la cual cuando está activada únicamente deja trabajar sobre ficheros que se encuentren en el directorio establecido en ella. Por lo tanto, obteniendo su valor (Select @@secure_file_priv) sabríamos dónde buscar. Por ejemplo, con sqlmap podríamos hacerlo de la siguiente manera:

./sqlmap.py -u "http://web.vulnerable" --data="post_data" -p variable_vulnerable
--string="string_que_se_muestra_cuando_TRUE" --sql-query="@@secure_file_priv”

Por último, una vez hemos encontrado el directorio sobre el cual está nuestro .htaccess simplemente nos queda ir leyendo carácter a carácter su contenido (donde sqlmap nos facilita mucho la faena):

./sqlmap.py -u "http://web.vulnerable" --data="post_data" -p variable_vulnerable
--string="string_que_se_muestra_cuando_TRUE" --sqlquery="
load_file(0x<path_fichero_en_hexadecimal>)"

Comments

  1. ¿Y si he configurado Apache para que el .htaccess se llame .acceso, y mantengo el .htaccess conteniendo «You shall not pass»?
    (Es gracioso porque lo hice una vez)