Vulnerabilidad en phpMemcachedAdmin

¿Qué es memcached? Memcached es un sistema de cache de objetos encargado de guardar los elementos cacheados en la memoria RAM del servidor, permitiendo acelerar el acceso a los mismos. Utilizando el script phpMemcachedAdmin es posible observar en tiempo real información sobre el estado y el funcionamiento del servicio Memcached, y datos del funcionamiento de un cluster de varios servidores Memcached. Otra funcionalidad que ofrece es la posibilidad de ejecutar comandos en Memcached directamente desde la interfaz web.

Pero no todo lo que reluce es oro, ya que no posee ningún sistema de autenticación de acceso y, en la mayoría de las veces, la persona “responsable” lo suele dejar accesible para cualquier usuario desde Internet. Pocos sitios implementan una “barrera” de seguridad mediante la utilización de ficheros .htaccess y .htpasswd, y los problemas pueden surgir cuando se encuentra una vulnerabilidad que compromete la seguridad como la que se expone en este artículo.

Existe una vulnerabilidad en la versión 1.2.2 y anteriores de phpMemcachedAdmin que podría permitir a un atacante la ejecución de código remoto. Aunque es pública, no está muy documentada y como veremos al final aún hay un buen número de sistemas vulnerables, por lo que vamos a analizarla un poco.

En la descripción del CVE asociado (CVE-2014-8731) se menciona que parte de los datos serializados y la última parte del nombre de archivo concatenado puede ser especificado por un usuario. Se puede entender a qué se refiere si se analiza el contenido del fichero stats.php. El problema reside en el manejo de las peticiones, las cuales se identifican mediante la utilización de cookies. Observando el código se pueden encontrar las líneas que se encargan precisamente de esto y un comentario del desarrollador avisando que debe ser corregido, ya que no se trata de un método perfecto.

mm1

Básicamente se comprueba si existe una cookie que haya sido creada con anterioridad para esa petición, y si no existe se crea. El contenido de ésta es exactamente el valor que posee la variable live_stats_id, que en este caso corresponde al valor aleatorio devuelto por la función rand() concatenado con el valor de la variable hash, el cual se obtiene calculando el hash MD5 del valor pasado a través del parámetro cluster, que no es más que el nombre del cluster del que se está consultando el estado.

Una vez creada la cookie, el script define una ruta de fichero que posteriormente será utilizada para guardar los datos sobre el estado del cluster.

mm2

Se puede observar que como nombre de fichero se utiliza la concatenación de la cadena live_stats. y el contenido de la variable live_stats_id. Es aquí donde se encuentra el error que permite explotar la vulnerabilidad. En un principio cuando la cookie se crea por primera vez, el valor de la variable live_stats_id es calculado por el script pero, ¿y si la cookie ya existe?

mm3

Si la cookie ya existe, se ejecuta la sentencia else donde la variable live_stats_id toma como valor el contenido de dicha cookie, si este es modificado, el nombre del fichero también. Esta tarea es fácil de llevar a cabo utilizando, por ejemplo, una herramienta como Cookie Manager. Si se modifica el contenido por /../../test.php la ruta del fichero sería Temp/live_stats_id./../../test.php, creando en el directorio raíz de la aplicación un fichero llamado test.php, al que se puede acceder y ver su contenido.

mm4

Dentro del fichero se encuentran los datos del estado del cluster para el que se ha realizado la petición. Estos son recopilados y almacenados en una variable de tipo array ($actual), cuyo contenido se vuelca al fichero generado.

mm5

Si se accede a la pestaña de editar la configuración se puede observar como el nombre definido para el cluster es uno de los parámetros que se guarda en el fichero.

mm6

¿Qué pasaría si se modifica ese dato concreto y se inserta en su lugar, por ejemplo, código php? Pues como era de esperar, la entrada de datos no es sanitizada y el código php se inserta en el fichero. Por lo tanto, con una simple línea de código como la siguiente se podría obtener una shell simple que permita ejecutar comandos remotamente en el servidor.

<?php system($_GET[‘cmd’]); ?>

Una vez sustituido el nombre del cluster es necesario acceder nuevamente a consultar el estado del mismo, ya que de esta manera se sobrescribe el contenido del fichero que se había creado previamente haciendo posible la ejecución remota de código.

mm7

Los comandos son ejecutados con los permisos del usuario en ejecución. A partir de aquí las posibilidades son muchas, como ejecutar un comando wget para descargar una WebShell más completa, intentar una escalada de privilegios, etc. Como se puede observar la prueba de concepto ha sido realizada en un entorno virtualizado, pero actualmente es posible encontrar un número considerable de sitios web que utilizan el script phpMemcachedAdmin y es relativamente fácil encontrarlos mediante técnicas de dorking en buscadores.

El resultado es bastante preocupante, ya que según Google unos 1400 sitios web han dejado accesible a cualquier usuario de Internet su panel de administración de phpMemCachedAdmin. No seáis malos…