lunes, 5 de agosto de 2013

Joomla "com_media" Unauthorised Uploads

Esta vulnerabilidad se ha publicado hace poco (01/08/2013) en el "Vulnerable Extensions List" de Joomla (vel.joomla.org). Se trata de un filtrado incorrecto en el componente "com_media", que es parte del core de Joomla y se encarga de la gestión del contenido multimedia (imágenes). Esta vulnerabilidad permite subir ficheros no autorizados al servidor lo que podría terminar en una ejecución de código PHP.

En este post quiero hacer un análisis de esta vulnerabilidad y mostrar como explotarla.

Pero primero...

Referencias:
Empecemos...

Escenario

El escenario en donde esta vulnerabilidad nos puede ser útil es cuando tenemos acceso al módulo "com_media" de Joomla pero con un rol de bajos privilegios como: author, editor, publisher o manager. Estos roles tienen los permisos suficientes para usar el Media Manager (com_media) pero no para cambiar su configuración.

Análisis

El "Media Manager" de Joomla es el componente que utilizamos para subir imágenes e insertarlas en los artículos. Por defecto solo deja subir ficheros cuya extensión se encuentre dentro de una lista blanca de extensiones permitidas.

Fig. 1 - Extensiones permitidas por el "Media Manager".

El código que se encarga de validar esto es el siguiente:

administrator/components/com_media/helpers/media.php
     $format = strtolower(JFile::getExt($file['name']));
 
     $allowable = explode(',', $params->get('upload_extensions'));
     $ignored = explode(',', $params->get('ignore_extensions'));
     if (!in_array($format, $allowable) && !in_array($format, $ignored))
     {
         $err = 'COM_MEDIA_ERROR_WARNFILETYPE';
         return false;
     }

La variable "$allowable"  es un array con las extensiones permitidas y la variable "$format" contiene la extensión del archivo que intentamos subir. En el "if" se valida que la extensión de nuestro archivo esté dentro de la lista de extensiones permitidas, si no está retornará falso, es decir impedirá la carga del archivo. Además vemos que también se valida otra lista de "extensiones ignoradas" que están en la variable "$ignored". Pero por defecto esta lista está vacía.

Fig. 2 - Extensiones ignoradas por el "Media Manager".

Se podría suponer entonces que la variable "$ignored" es un array vacío. Pero esto no es cierto. La expresión "$params->get('ignore_extensions')" efectivamente devuelve una cadena vacía. Pero luego, al aplicar "explode" sobre esta cadena vacía, el valor devuelto es un array que contiene como único elemento la cadena vacía.

Fig. 3 - Comportamiento de la función "explode".
Más info: http://php.net/manual/es/function.explode.php

En consecuencia tenemos que las extensiones vacías también son permitidas por el Media Manager.

Ahora analicemos la función "getExt" de la clase "JFile" que es la utilizada por Joomla para obtener la extención de un fichero.

libraries/joomla/filesystem/file.php
    public static function getExt($file)
    {
        $dot = strrpos($file, '.') + 1;

        return substr($file, $dot);
    }

Básicamente lo que hace esta función es devolver lo que continua después del último caracter "." (punto) en el nombre del archivo. Entonces podemos conseguir que la función "getExt" devuelva una "extensión vacía" enviando un archivo con un "." (punto) al final del nombre y de esta manera "bypassear" la validación de extensiones del Media Manager.

Fig. 4 - Prueba de "Upload bypass"

Explotación paso a paso
  1. Iniciar sesión en Joomla
  2. Acceder al Media Manager

    http://servidor.com/index.php?option=com_media&view=images&tmpl=component&asset=com_content
  3. Crear una webshell con el nombre: "shell.php."
  4. Subir la webshell con el Media Manager
  5. Ejecutar la webshell:

    http://servidor.com/images/shell.php.

¿Se ejecutó? ¿Sí? ¿No? La verdad es que en un servidor bien configurado la extensión ".php." no debería ejecutarse. Todo depende de como esté configurado el módulo de php en Apache.

Más info: http://blog.famillecollet.com/post/2013/01/13/PHP-and-Apache-SetHandler-vs-AddHandler

Dicho sea de paso, en Centos (al menos la versión 6.4) la configuración por defecto de Apache es vulnerable y el archivo sí se ejecuta.

Demo



Un saludo.

2 comentarios:

  1. Acabo de probarlo, y bueno no se ejecuto. Supongo que es mi mala suerte o el servidor esta bien configurado. xD

    ResponderEliminar