Buscar y eliminar código malicioso en PHP v.2

Basándome en la 1ª versión del buscador-eliminador de código malicioso he re-programado el script para que sea más sencillo el poder añadir los diferentes códigos que nos vayamos encontrando.

Actualizaciones:

17/01/2014: Añadida nueva expresión regular para encontrar código malicioso “document.write(…” en .js
17/01/2014: Añadida revisión de ficheros .js

Antes de nada quiero agradecer a Victor el aporte de uno de los códigos maliciosos encontrados.

En la versión anterior, todo el código de búsqueda y eliminación se centraba en buscar el código eval(base64_decode(“…==”)) para el borrado de dicho código y por el camino buscar algunas posibles vulnerabilidades (como la inclusión de iframes, scripts que cargaban php externos, etc); todo ello gestionando linea a linea cada fichero desde la función aplicar_eval(). El gestionarlo línea a línea se hacía para que llegado el momento pudiésemos saber donde había que hacer la revisión manual o donde se había borrado, pero realmente el borrado era algo indiferente, ya que al borrarlo daba igual que fuéramos a buscar dicha linea. Por lo tanto lo que he hecho en un primer momento ha sido separar la eliminación directa del código conocido de la búsqueda por lineas del posible código a revisar manualmente. Por otro lado, en lugar de tener que ir añadiendo condiciones y comprobaciones a la función, he sacado las expresiones regulares a un array externo, de manera que cada vez que se encuentren nuevos códigos se podrán añadir fácilmente al comienzo del fichero.

La función recorrerDirectorio() se mantiene prácticamente intacta, por lo que obviaré comentar nada sobre ella, lo único nuevo es que se le pasan dos nuevos parámetros (los arrays de busqueda) y que devuelve un mensaje para mostrarlo por pantalla al finalizar.

1º Cambio importante: los arrays de expresiones regulares:

Tendremos dos, uno para el código malicioso conocido y otro para el “posible” código malicioso que se deberá revisar a mano, la forma de gestionarlo será la siguiente:

Algunos de los códigos que tenemos hasta el momento son el eval base64_decode indicado anteriormente, el applyfilter aportado Issux en el post indicado anteriormente y el zen_framework que me he encontrado en otra web, con lo que el array malicioso quedaría de la siguiente forma:

En todos los casos, el texto de sustitución es cadena vacía, pero me he encontrado uno en concreto en el que se comprueba si hay un post y en ese caso se lanza una llamada a una función check_fsockopen, el problema en este caso es que no soy capaz de hacer que me detecte la ultima llave del cierre de la condición, por lo que en su defecto lo voy a parchear de la siguiente forma:

Eso lo único que hará será sustituir todo ese código malicioso por :

con lo que al menos el mal está arreglado temporalmente y ya no se ejecuta el código malicioso.

Por otro lado tenemos el array de posibles códigos maliciosos, que se basa en la busqueda del eval sin los iguales al final, de iframes, etc. El array quedaría de la siguiente forma:

En ambos casos indicamos lo que se debe de buscar para que sea mas sencillo para el programador revisar el error, la linea se añade automáticamente.

A esos dos arrays se irán añadiendo todos los códigos maliciosos que se vayan encontrando, dependiendo del tipo que sea se añadirá a uno para eliminarlo u a otro para mostrar la linea en la que se encuentra, ya me he encontrado varios nuevos pero tengo que preparar las expresiones regulares, por lo que por el momento nos vamos a conformar con los del eval, el applyfilter y el zen_framework.

2º Cambio importante: la función revisar_fichero():

Para el array_malicioso se realizará una sustitución directa, sin buscar por lineas, con lo que nos evitamos ese primer recorrido, y para el array de posibles se llamará a la función revisar_posibles(), anteriormente llamada aplicar_eval(). Como ya está bastante comentada en el código evito aburriros con explicaciones innecesarias.

3º Cambio importante: la función revisar_posibles():

De igual forma que la anterior, recorre el array de posibles, esta vez recorriendo el fichero linea por linea indicando en cual se encuentra el posible código malicioso en caso de encontrarlo:

Poco mas queda que decir, salvo que parece que este código es bastante mas rápido que el anterior, ya que para un mayor numero de ficheros buscados en la prueba, y un número similar de código revisado, el tiempo de ejecución ha sido bastante mas bajo: de 17  a 5.29598 segundos con un 99% de código malicioso borrado (unos 789 ficheros limpiados), el resto fue revisar los posibles, y me llevó unos 10 minutos aprox.

Aquí os dejo el fichero completo que solo tendréis que subir a vuestra capeta raíz en el servidor y ejecutarlo:

Actualizaciones:

17/01/2014: Añadida nueva expresión regular para encontrar código malicioso “document.write(…” en .js
17/01/2014: Añadida revisión de ficheros .js

Descargar script de limpieza

(Nota: no he añadido aún el código del check_fsockopen, lo haré en el momento que haya depurando la expresión regular)

Recordad, si encontráis nuevos códigos maliciosos podéis ir comentándolos aquí para ir añadiéndolos a los arrays de búsqueda, no enlacéis directamente a las webs infectadas. Se irán añadiendo a este post los códigos y se irá actualizando el fichero (tranquilos, iré avisando de cada actualización).

También se agradece cualquier “me gusta”, tweet, o +1 con el que queráis colaborar jaja.

28 Comentarios

  1. He puesto el script a la carpeta raíz, pero no rula (libreríallerapacios.com/limpieza.php).
    Mi problema es que no hay ninguna página web que encuentre el código malicioso de mi sitio web. (He usado sitecheker y otros).
    Todo empezó cuando instalé un pluguin con puerta trasera. Si yo ahora pongo un pluguin para activar SSL en wordpress o activo la casilla de forzar pagos seguros (SSl) de woocommer, algo se me activa, y se le doy al botón de pagar, mi cuenta o al botón de ir a caja, se me redirije a otra página web. Evidentemente tengo desactivado la opción de SSL y parece que todo funciona bien.
    Me gustaría saber cómo puedo solucionarlo, ya que tu SCRIPT parece una gran idea, pero no me funcina y el problema persiste.

    Gracias.

    • admin

      Hola Espo.
      Es posible que el código malicioso que esté dando problemas en tu web sea diferente a los que están contemplados en el script de limpieza (códigos maliciosos hay miles, y con que nos cambien cualquier carácter ya puede implicar que no se encuentre correctamente), en cualquier caso he entrado a la url de limpieza y se me ha quedado bloqueado, no ha devuelto ningún resultado (si todo estuviera bien devolvería un “no se ha encontrado código malicioso”, pero por defecto al menos te debería devolver algún aviso de revisión de ficheros .htaccess, que se hace por precaución) y ni siquiera ha completado el html de limpieza.php. Es posible que el tiempo de ejecución de tu servidor sea menor que el necesario para realizar la operación, por lo que se queda parado antes de finalizar. ¿Podrías consultar a los que te llevan el alojamiento cual es ese tiempo de ejecución?

      Por otro lado, he entrado a la web desde google y no me ha dado ningún aviso de spam, posiblemente por lo que comentas de que lo tienes desactivado.
      Si quieres puedes enviarme un mp (desde la sección “contacto”) con los datos de acceso a tu ftp (un usuario temporal en modo de solo lectura), me descargo los ficheros y ejecuto la limpieza en mi servidor local, es posible que encuentre algún código que no esté contemplado y pueda añadirlo al script

      Un saludo.

  2. Mamen

    Hola y, ante todo, gracias por tu ayuda.
    El pharma hack nos ha golpeado y para aquellos pequeños negocios que actualmente no podemos contratar gente especializada para solventarlo, es una ayuda tremenda.
    Acabo de subir y ejecutar el script y creo que lo primero que hay que hacer es arreglar el htaccess para mejorar las restricciones de seguridad. Hay mil y una recomendaciones diferentes al respecto y me gustaría saber si tienes algún consejo o un htaccess “perfecto” recomendado.
    Gracias nuevamente y un saludo,

    • admin

      Hola Mamen.

      No estoy muy seguro de cual sería la configuración perfecta para aumentar la seguridad del htaccess, pero se podría evitar que se accediera a él usando el siguiente código:
      <Files ~ "^\.ht">
      Order allow,deny
      Deny from all
      Satisfy All
      </Files>

      Ojo, este código se suele usar cambiando el <Files ~ “^\.ht”> por <Files “nombre_fichero.ext”> para evitar el acceso a se nombre_fichero.ext, en el código de arriba está preparado para evitar el acceso a cualquier fichero que contenga la cadena “.ht” sin importar las mayusculas/minusculas y el único fichero que cumple esas características suele ser el .htaccess.
      Ese podría ser un comienzo, a partir de ahí se podría comenzar a añadir seguridad por si lo anterior falla (a mi en local me está dejando acceder y abrir el .htaccess), un comienzo sería el siguiente:
      <IfModule mod_rewrite.c>
      #bloqueo por HTTP_USER_AGENT, HTTP_REFERER y REMOTE_HOST
      RewriteBase /
      #los robots que comienzan con:
      RewriteCond %{HTTP_USER_AGENT} ^Anarchie [NC,OR]
      RewriteCond %{HTTP_USER_AGENT} ^ASPSeek
      #los robots que contienen:
      RewriteCond %{HTTP_USER_AGENT} ^.*casper [NC,OR]
      #dominios concretos
      RewriteCond %{HTTP_REFERER} ^http://.*dominiomalicioso\.com [NC,OR]
      RewriteCond %{REMOTE_HOST} ^.*\.dominiomalicioso\.com$ [NC,OR]
      #host que comienzan por mail o smtp
      RewriteCond %{REMOTE_HOST} ^mail(.*)\. [NC,OR]
      RewriteCond %{REMOTE_HOST} ^smtp(.*)\. [NC,OR]
      #evitamos ataques via $_GET[]
      RewriteCond %{REQUEST_METHOD} GET
      RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
      RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http%3A%2F%2F [OR]
      RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
      RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC]
      #devolvemos el error 403 (prohibido)
      RewriteRule ^(.*)$ - [F]
      # Evitamos que se pueda insertar la web en un iframe. OJO: si tu web usa popups en iframe devolvería el mismo error.
      Header set X-Frame-Options DENY
      </IfModule>

      en fin, todo sería cuestión de ir investigando posibles medidas de seguridad, creo que me voy a preparar un post sobre el tema, porque casi todo lo que he encontrado estaba en ingles o repartido por varias webs.

      Espero haberte ayudado.

      Un saludo y gracias por tu comentario.

  3. He insertado el script en una de mis webs, pero no se como se ejecuta. El script está en la raíz: http://www.bunkerlab.com/limpieza.php

    ¿Cómo lo ejecuto? Es un wordpress.

    • admin

      Hola Nuria. He intentado acceder a la url de limpieza (http://www.bunkerlab.com/limpieza.php) y me ha devuelto una página de error propia del wordpress; lo estabas haciendo bien, solo tienes que subir el fichero a la raiz servidor (supongo que lo habrás subido a la raiz, justo donde tienes el index.php) y realizar la llamada a la url, tras ello te mostrará un mensaje con los ficheros limpiados y los posibles errores o simplemente un mensaje donde te dice que no tienes código malicioso conocido; si no es así (que es lo que esta pasando) es posible que tengas alguna limitación por .htaccess que tengas que revisar (que solo se pueda acceder desde el index.php por ejemplo con lo que tendrías que añadir el limpieza.php para evitar esa limitación).

      Un saludo y gracias por tu mensaje.

  4. He ejecutado tu utilidad y funciona de maravilla, muchas gracias. Me ha limpiado muchos archivos, pero en otros me dice q lo haga manualmente y que me dice “Busca iframes o includes javascript hacia ficheros .php y comprueba si son necesarios para el funcionamiento normal”, pero no soy capaz de distinguir esto, alguna pista?, muchas gracias de nuevo

    • admin

      Hola Pablo. Me alegra que te haya podido ayudar en un porcentaje alto. El resto de ficheros en los que te dice que tienes que buscar iframes etc, es debido a que ciertas partes de wordpress usan iframes e includes para el correcto funcionamiento por lo que no los podemos eliminar directamente. La mayor parte de lo que te muestre serán ficheros correctos pero si en alguno de ellos ves que enlazan a páginas externas posiblemente sea código malicioso.

      Si quieres puedes usar esta web para pegar los códigos en los que estás dudando, te generará un enlace y solo me lo tienes que pegar en un comentario para revisarlo: http://pastebin.com/

      Un saludo y gracias por tu mensaje.

  5. Pablo

    Ya esta todo solucionado, gracias. Los del servidor me han hecho una auditoria y esta todo correcto. Pero el destrozo que te hace esto es increible, he tenido que actualizar todo y borrar un monton de cosas que apenas usaba. Y ya google me ha quitado la marca de sospecha. ¿Como se hizo este ataque tan brutal? Gracias.

    • admin

      Uf, no sabría decirte en concreto, puede ser porque hayan podido saber el usuario y contraseña de tu ftp, o de tu usuario de worpdress y hayan entrado, también puede ser por haber instalado algún plugin peligroso… es difícil saberlo a ciencia cierta.

      En cualquier caso me alegro que se haya solucionado tu problema y que el script te haya podido ayudar en algo.

      Un saludo.

  6. Juan Carlos

    Hola, lo primero de todo decirte que me ha resultado muy interesante tu post.

    Me he descargado el script y al ejecutarlo me dado el siguiente error:

    Fatal error : Call to undefined function: file_put_contents () en / var / www / vhost / nombredeldominio.com / home / html / limpieza.php on line 227

    ¿Alguna solución?

    Gracias anticipadas por la respuesta.

    • admin

      Hola Juan Carlos, file_put_contents() es una función añadida en la versión 5 de PHP, es posible que el servidor en el que tienes alojada la web tenga una versión anterior, por lo que no reconoce dicha función. Puedes consultarlo con el servicio técnico de tu alojamiento y si es así es posible que se pueda actualizar a la versión 5 (existen alojamientos donde no se puede)

      Por mi parte lo que puedo hacer es preparar una versión para PHP < 5, aunque estos días estoy algo liado con “trabajo extra” y tengo que aplazarlo unos días. Siento no poder ser de mas ayuda en estos momentos. Un saludo y gracias por tu respuesta.

    • admin

      Por cierto, si el script de limpieza ha llamado a esa función es que obviamente ha encontrado un código que debe ser eliminado, si google está bloqueando tu web por culpa del malware y necesitas que tu web sea visible cuanto antes siempre podrías enviarme los datos de acceso a tu ftp desde la sección “contactar” (solo me llega a mi y no se publican en ningún lado), descargarme el contenido y ejecutar el script en mi servidor local, para volver a subirlo ya limpio.

      Un saludo.

  7. hola buen post muy interesante por cierto si instalo una plantilla que trae base 64 y ejecuto ese archivo de limpieza me limpia todo el codigo malicioso que tenga el nulled?

    • admin

      Hola marcelo. El código solo eliminaría los eval(base64_decode(..==)) que sabemos que son maliciosos, el resto de códigos te los mostraría como posibles y tendrían que ser revisados a mano. En cualquier caso, hemos comprobado en las últimas webs que hemos revisado que casi todos los eval(base64_decode()) son maliciosos aunque no lleven el “==”. Un base64_decode por si solo no dará problemas, es el eval el que ejecuta el código por lo que el encontrarlos por separado no implica que sean maliciosos. Por lo que en ambos casos no tendrías que preocuparte por borrar de menos o de mas.

      Un saludo y gracias por tu mensaje.

  8. Hola, soy nuevo en este tema, he descargado el archivo .rar, lo descomprimí, entiendo que debo entrar con ftp a mi sitio y subir el archivo “limpieza.php” en el sitio donde está mi página, esto es correcto? en que ubicación lo subo? y como lo ejecurto? no entiendo lo de ” realizar la llamada a la url”. Te agradezco la ayuda.

    • admin

      Hola Milton.

      Si, tienes que subir el fichero a la raíz de tu web, justo donde tienes el index.php (lo mas común es la carpeta “httpdocs” aunque dependiendo del servidor es posible que ya accedas directamente a la raíz de tu sitio) y lo llamarías con http://www.tuweb.com/limpieza.php

      Un saludo y gracias por tu comentario.

  9. Hola, gracias por la respuesta. Hice como me dijiste, luego trato de ejecutar el limpiador pero le lleva a la siguiente URL http://us.yhs4.search.yahoo.com/yhs/errorhandler?hsimp=yhse-001&hspart=CND&type=AC538ED8F251F4DD7B5F_s11_g_e&q=https://www.cedic.com.ar/limpieza.php/
    y no pasa nada más.
    Te comento que al tratar de entrar a mi web se abre una ventana de alerta de AVG que dice que se bloqueó amenaza, ataque de vulnerabilidad Blackhat SEO (type 1720)

  10. Lou gro

    Hola, yo subí a http://pastebin.com/4PU2r6rn lo que me encontré en el archivo functions.php del template del sitio, lo que yo supongo que es código malicioso esta como edoced_46esab(lave) y me costo mucho trabajo decodificarlo, ahora mi pregunta es… como debe de quedar el código sin esa instrucción…. agradeceré la ayuda proporcionada por que soy nueva en esto…

    gracias :-)

    • admin

      Hola Lou gro.
      Si no me equivoco, si eliminas todo el código que está entre “< ?php $wp_function_initialize" y "(edoced_46esab(lave'));?>” debería ser suficiente, por lo que ven en el pastebin que me has puesto es el único código malicioso que se ha añadido en el functions.php por lo que sería suficiente. En cualquier caso recuerda hacer una copia de seguridad de ese fichero.

      Un saludo y gracias por tu comentarios.

  11. Hola, gracias ante todo por el aporte. Yo tenía en mi web en una carpeta de imágenes un archivo “mailmand.php” que enviaba múltiples correos SPAM. Hoy la he eliminado del servidor, pero me dicen desde dondominio que hay archivos infectados, que lo solucione o me anulan el servidor. He subido el archivo y me muestra archivos posiblemente maliciosos, muchos de ellos los he abierto pero no sé distinguirlos, sobretodo los .js.
    Agradecería tu ayuda.

    • admin

      Hola maritrini, podrías indicarme la url a tu web para poder lanzar el script y ver los avisos que te muestra?. En muchos casos posiblemente sean simplemente avisos de que puede ser potencialmente peligroso (iframes, etc) pero que son usados en la web desde siempre. Si accediendo al script te puedo ayudar directamente perfecto; si no, es posible que necesitase ver el código fuente ya sea enviandome los ficheros comprimidos o dandome un acceso al ftp del alojamiento.

      Por el momento vamos a probar con lo primero.

      Un saludo y gracias por tu comentario.

  12. amigo he revisado mis instalaciones de wordpress y he encontrado este codigo como lo puedo borrar con su script

    [CÓDIGO MALICIOSO EDITADO]

    • admin

      Hola andres, he editado tu comentario para eliminar el código que has insertado para evitar posibles problemas.
      Con mi script no podrías borrar ese código concreto ya que no es un estandar y podría eliminarte partes del código necesarias para el funcionamiento de tu web, debe de eliminarse a mano, si quieres puedes enviarme el código del fichero .php donde se ha encontrado el posible código malicioso a ektoral(at)hotmail.com (en un fichero txt por ejemplo) y te lo puedo eliminar yo.

      Un saludo y gracias por tu comentario.

      • gracias admin por contestar.
        El problema es que este codigo esta situado en la primera linea de todos mis archivos .php del wordpress incluyendo core, plugins y themes.

        He tratado con este comando para comentarlo para al menos qde visible el sitio
        pero en los plugins hay que borrarlas por que si no, no funciona el plugin.

        dejo la link de comando
        sed -i ‘s/$nkwlfmhzne/\/\/$nkwlfmhzne/g’ *.php

        agradezco cualquier sugerencia respecto al caso

  13. Hola. . Estoy en el mismo caso que el amigo Andrés, temporalmente lo que estoy haciendo es sustituir en la primera linea de los php del sitio infectado la cadena $LetrasAleatorias = ‘aqui el codigo que inserta el virus o lo que sea….’ por //$LetrasAleatorias de manera que el codigo queda comentado y temporalemente el sitio se comporta como debe . .

    He estado varias horas pegandome con el código principal de esta pagina (que por otra parte me ha servido muy bien y agradezco en el alma al creador) y no veo manera de añadir (aunque haya que hacerlo a mano para cada dominio infectado) el ARRAY para que busque la cadena $LetrasAleatorias = ‘…. y lo sustituya por //$LetrasAleatorias

    Y digo que la solución es comentarlo porque los H.P (y no me refiero a las impresoras) que lo crearon varían en cada PHP la cadena insertada, de manera que no se puede buscar una cadena exacta. . .

    Se agradecerá una solución . . . Muchisimas gracias no obstante por el gran trabajo realizado en esta web.

  14. Ah!!, se me olvidaba poner . . la parte $LetrasAleatorias = es siempre la misma para cada sitio infectado, eso si, varía si tienes varios dominos infectados, de ahí que habría que modificar el fichero de limpieza por cada dominio a limpiar, o bien ejecutar primero un a solicitud (formulario) pidiendo la cadena que corresponde a sustituir a $LetrasAleatorias.

    Gracias.

    • admin

      Andres, Josema, antes de nada perdonad por la tardanza en responder, estos días he estado bastante liado y no he podido atender esta web tan rápido como me hubiera gustado.

      Josema, me dices que los caracteres aleatorios se asignan a esa variable “$LetrasAleatorias”, pero, luego se llama desde algún eval(base64_decode($letrasAleatorias)) o similar (que al menos lleve el eval o el base64_decode)?

      Ahora mismo, la primera de las opciones del array
      $array_malicioso['eval_base64_decode']=array('/eval\(base64_decode\(\"(.*==)\"\)\);/m',''); se usa para ese tipo de códigos, pero acabados en “==”, obviamente los que programa estos códigos maliciosos han evolucionada para evitar esas búsquedas, si este es el caso y aún así sigue usando el eval_Base64_decode se podría usar la opción anterior quitandole los dos “==”, pero aquí hay que tener cuidado, ya que tu web puede necesitarlo realmente en algún lado, tendrías que hacer una copia de seguridad antes de lanzar el código de limpieza. Si quieres, envíame las lineas de código malicioso en un txt a ektoral(at)hotmail.com para revisarlas y confirmarte si tendría que ser de esa forma.
      andres, te digo lo mismo, envíame el código en un txt para revisarlo y ver si te puedo ayudar en la web.

      Un saludo y gracias por vuestros comentarios.

Deja un comentario


*