lunes, mayo 08, 2017

Apache: Server-Side Session Hijacking con Virtual Hosts hackeados (2 de 2)

Tras haber concluido la primera parte de este artículo, espero haberte dejado intrigado y con ganas de saber cómo se podría hacer un Server-Side Session Hijacking en esa aplicación corriendo sobre un servidor Apache con PHP que hemos dejado bastante fortificado, así que espero que la segunda parte te responda a esa pregunta con algo de información nueva.

Figura 21: Server-Side Session Hijacking con Virtual Hosts Hackeados (2 de 2)

El truco que se puede utilizar es uno bastante sencillo, que está ahí, en muchos servidores Apache que corren sobre servidores GNU/Linux, y consiste en usar una de las características más conocidas de estos sistemas operativos.

Valor simbólico

Hay, al menos, una forma de "traernos" la aplicación víctima al servidor del atacante. Y la que se me viene a la cabeza utiliza una característica del sistema de ficheros: los enlaces. El usuario "net" no puede crear un enlace duro (hard link) al script "index.php" de la aplicación víctima ya que carece de los permisos necesarios. Pero no hay problema para crear enlaces simbólicos. De modo que si ejecutara un comando como el que sigue:
ln -s /var/www/html/com/index.php /var/www/html/net/app.php
...creando un enlace en el virtual hosts del atacante que respondería ante una petición del tipo:
http://danger.example.net/app.php
... entonces el servidor Apache se encontraría con el enlace simbólico:
 "/var/www/html/net/app.php".
Y en esa situación, lo que pueda hacer con él dependerá de la configuración que tenga establecida. Lo más frecuente, y lo que me encuentro en este caso, es que esté activada la opción FollowSymLinks. Esto quiere decir que Apache seguirá el enlace simbólico que le llevará a "/var/www/html/com/index.php".

Y lo abrirá con los permisos de su propietario, "com", y comenzará a interpretarlo. Pronto llegará a una sentencia que da más de pensar de lo que a primera vista parece:
require_once "include/login.inc.php";
Vale. Necesitamos leer el fichero "include/login.inc.php". Pero ¿de qué directorio? La documentación de PHP señala que, para cosas como "require_once" que leen ficheros, existen tres posibilidades:
- Que la ruta de fichero sea absoluta. Del tipo "/var/www/html/index.php". En este caso, está claro el fichero que hay que leer. 
- Que la ruta de fichero comience con "./" o "../", para el caso de sistemas *nix, o ".\" o "..\" para Windows. Entonces la ruta se considera relativa al directorio actual. 
- En otro caso, PHP utiliza una variable de configuración llamada "include_path" que contiene una lista de directorios. Si no encuentra el fichero a cargar en ninguno de ellos, lo intenta con el directorio en el que se encuentra el script. Y, si aún sigue sin encontrarlo, busca en el directorio de trabajo actual.
En el caso de la aplicación víctima tenemos esta última situación. Con una condición curiosa:
- El directorio del script, el que se pidió a Apache, es "/var/www/html/net", controlado por el atacante. 
- El directorio de trabajo es "/var/www/html/com". El de la aplicación víctima.
Gracias a esto, el atacante podría redefinir algunos de los ficheros utilizados en los "require", "require_once", etcétera.

Figura 22: Documentación de inlude & require en PHP

Para ello le basta con crear en su directorio una estructura de directorios similar a la de la aplicación, crear en ella los ficheros que necesite "ajustar" a sus necesidades y asegurarse de que el usuario "com" puede acceder a todo ello. Para lo que necesite la aplicación y no se halle en los directorios del atacante, ahí estará PHP, que se encargará de buscarlo en el directorio de la propia aplicación víctima.

Al ataque

Ya sabemos lo que hay que hacer, de modo que tomamos la shell PHP y nos ponemos a ello. En este caso, redefinimos sólo el fichero "login.inc.php" en el lado de la aplicación atacante para que, sin necesidad de hacer nada, nos cree una sesión con privilegios de administrador:

Figura 23: Creando el login.inc.php alternativo

Aunque los nuevos "app.php" y "login.inc.php" estarán alojados en "/var/www/html/net", el usuario "com" podrá leerlos. Ahora, si visitamos "http://danger.example.net/app.php"...

Figura 24: Accediendo a las opciones de administración

En la imagen superior puede observarse que hemos conseguido acceder a las funcionalidades de administración de la aplicación. Además, la información de diagnostico indica que el proceso está ejecutándose con la cuenta "com".

Por otro lado, en la parte inferior se aprecia que se han usado las herramientas para desarrolladores para obtener el valor de la cookie que se acaba de recibir. Una cookie a la que el usuario "com" sí podrá acceder, pues fue él mismo quien la creó. De modo que, si ahora cargamos "http://webserver.example.com" y se la forzamos:

Figura 25: Forzado de la cookie de sesión

Y ahora, si recargamos la página, obtenemos las opciones de administración.

Figura 26: Hemos hecho el Server-Side Session Hijacking desde
un virtual host hackeado en un Apache con seguridad mejorada.

Y podremos seguir con nuestra sesión sin problemas. Y con privilegios de administración. Así que la fortificación de Apache no ha sido todo lo eficaz que deberíamos esperar, y hay que hacer alguna cosa más para evitar este tipo de ataques. Vamos a ver qué se podría hacer.

Tratar de arreglar las cosas

En casos como éste, poner soluciones es tarea tanto de los desarrolladores de la aplicación como de los administradores del servidor. Y, además, ambos deben tratar de afrontar todos los posibles problemas: ni los desarrolladores deben dar por supuesto que los administradores han configurado el equipo de forma segura. Ni los administradores deben confiar en que las aplicaciones que instalan están bien desarrolladas.

Los desarrolladores podrían haber cambiado las rutas de las que se hace el "require_once" y haberlas convertido en absolutas. Con valores como "/var/www/html/com/include/login.inc.php", poco margen habría quedado para la manipulación.

Debe señalarse que en este caso de nada habría servido que las rutas se hubieran indicado de forma relativa comenzando con "./". Como en "./include/login.inc.php". De hacerlo, las peticiones realizadas a "http://danger.example.net/app.php" serían servidas tomando "/var/www/html/net" como directorio base y al atacante le habría bastado con redefinir - o crear enlaces simbólicos a - todos los ficheros en el directorio "include" de la aplicación víctima.

Figura 27: SymLinksIfOwnerMatch en documentación de Apache

En cuanto a los administradores, hay que recalcar que el uso de "FollowSymLinks" podría haber sido sustituido por "SymLinksIfOwnerMatch", que sólo sigue los enlaces simbólicos si el propietario del enlace es el mismo que el del fichero de destino. Algo que, por otro lado, aparece etiquetado muchas veces como poco recomendable en Internet por sus efectos sobre el rendimiento.

Otra importante mejora sería utilizar "ruid2" en modo "config". Para ello, en el fichero "apache.conf" habría que sustituir el RMode stat por RMode config y añadir unas líneas a la configuración de cada sitio virtual en el fichero "/etc/apache2/sites-enabled/000-default.conf", dejándolo como sigue:

Figura 28: Configuración de sitios virtuales modificada

De este modo se asegura que todo lo que se pida usando el nombre de servidor "danger.example.net" va a ser procesado usando los privilegios de la cuenta "net" y el grupo "net", lo cual evitaría la escalada de privilegios mostrada anteriormente.

Pero quizá pudiera hacer posible otras). Por ejemplo, si se pudiera crear un fichero en una carpeta cualquiera de otro host... ¿quién sabe?. Y pueden presentarse otros ataques de naturaleza diferente que pudieran terminar consiguiendo el mismo efecto. U otro distinto. Puestos a aislar, quizá lo mejor sea dejarse de complicaciones y utilizar una máquina, posiblemente virtual, para cada aplicación. Y, aún así, nunca se sabe.

Conclusión

Al final, la aplicación sí era vulnerable. Muy vulnerable. Al menos, bajo ciertas condiciones. Algo que no es poco frecuente. Los desarrolladores crean un producto y, según lo finalizan, suelen perder control sobre él. No pueden determinar completamente en qué circunstancias está siendo utilizado, qué configuraciones le dan soporte, qué entorno lo rodea, etcétera.

Todo esto que no pueden controlar, deben tratar de preverlo en las etapas de diseño. Ponerse siempre en el peor de los casos: cuando todo falla y, además, hay alguien que intenta sacar partido.

Hablando de la aplicación utilizada en este artículo, los desarrolladores posiblemente deberían, entre otras cosas, haber tomado medidas que evitaran el acceso a las variables de sesión, tanto para lectura como para escritura, por parte de otras aplicaciones. Quizá, cifrando su contenido y manteniendo un hash que permitiera detectar cualquier cambio no autorizado.

Al fin y al cabo, estamos hablando de "confidencialidad" e "integridad". Y eso es parte de la seguridad. Pero, ¿cómo de frecuente es encontrarse estas medidas de protección? ¿y cómo de habitual el no encontrarlas? Si tienes experiencia, tú tendrás una buena estimación.

ANEXO: La aplicación

Solo por responder cualquier duda que pudiera salir, os dejo los códigos utilizados en esta aplicación, para que podáis tener toda la información de lo que se ha presentado en este entorno

Figura 29: Index.php

Figura 30: include/Login.inc.php

Figura 31: include/app.inc.php

Figura 32: include/diag.inc.php

Figura 33: js/1.js

Autor: Enrique Rando, escritor de los libros "Hacking con Buscadores", Hacking Web Applications: SQL Injection y "Hacking Web Technologies" de 0xWord.

No hay comentarios:

Publicar un comentario