19 de octubre de 2009

DoS en Wordpress via TrackBackr

¿Que es TrackBack?


TackBack es un sistema de notificación de mención, es decir, sirve para saver quien ha mencionado o escrito sobre tu post.

¿Como funciona TrackBack?


Para informar al blog de que se escribe sobre lo primero es que tiene que tener el sistema de TrackBack.

Mandaremos a una petición POST al sitio que vamos a mencionar. La patición HTTP seria algo así:
POST http://www.example.com/trackback/ID
Content-Type: application/x-www-form-urlencoded; charset=utf-8

title=Mencion+sobre+ID&url=http://www.mi-blog.com/mencion&excerpt=Mi+Entrada&blog_name=Mi+blog

Las variables del POST son:

  • url: Direccion del blog permanente de la entrada (Obligatoria)

  • title: Titulo de la entrada (Opcional)

  • except: Nombre de la entrada (Opcional)

  • blog_name: Nombre del blog (Opcional)


La variable charset se encuentra en el valor de la cabecera Content-Type, en el ejemplo utf-8

Como respuesta ha este POST obtendremos lo siguiente en caso de que todo sea correcto:
<?xml version="1.0" encoding="utf-8"?>
<response>
<error>0</error>
</response>

En caso de error:
<?xml version="1.0" encoding="utf-8"?>
<response>
<error>1</error>
<message>Mensaje de error</message>
</response>

Las variable

¿Que errores se cometen?


En el caso del ejemplo anterior basado en uno de las especificaciones en el valor de Content-Type contiene el valor de charset. En Wordpress el valor de charset es obtenido mediante $_POST['charset']. Este error puede ser poco importante si el resto de aplicaciones que se comunican con el lo hacen igual.

El error de denegación de servicio es causado al no filtrar correctamente el valor de la variable charset que es recibido.

Con el valor de este dato se llama a la función mb_convert_encoding() para cambiar el tipo de codificación a la base del datos del blog.
Si se inserta como valor de charset varias codigicaciones separadas por ',' esta llamada se convierte en una operación muy pesada. Si se realizan varias conexiones el servidor atacado se queda rapidamente sin recursos.

Parche


El parche propuesto por el descubridor:
$charset = str_replace(",", "", $_POST['charset']);
if(is_array($charset)) { exit; }

El parche que propongo yo:
if(isset($_POST['charset']))
$charset = $_POST['charset'];
if (is_array($charset))//Si es un array da error
trackback_response("charset is array");
if(strpos($charset, ",") !== false)//Si tiene una , da error
trackback_response("charset have many values");

Referencias:


Especificaciones de trackback
Prueba de concepto
Más datos sobre el DoS

4 comentarios:

  1. Tackback o trackback... creo que comistes una r compañero, nos vemos en la siguiente de bloguerones. Un saludo :D

    ResponderEliminar
  2. Actualizado, gracias Antonio

    ResponderEliminar
  3. Sólo como apunte, la última condición del parche no está procesando como debería:
    if(!strpos($charset, ",") - Procesar si NO TIENE coma o la tiene en primera posición.

    Lo que queremos comprobar es si hay una coma, sea en la posición que sea. No obstante, strpos() devuelve un número entero, de forma que si encuentra una coma en la primera posición la función devolverá 0 (false).

    De tal forma que la condición debería ser
    if(strpos($charset, ",") !== FALSE) - La comprobación de tipos es importante.

    Espero haber aportado mi granito de arena.
    Un saludo, y buen trabajo.

    ResponderEliminar
  4. Muchas gracias por la correción.
    Yo lo habia echo así porque daba por echo que no estaba en la primera posición. De todos modos el peligro de este bug es poque hay varios charset en vez de uno, concatenados por ','; si el charset es incorrecto no se produce el DoS (en caso de que sea ',' como primer caracter).

    ResponderEliminar