Descubriendo SC: la amenaza persistente en WordPress para sysadmins Linux
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 30 minutos a 2 horas dependiendo de la complejidad del entorno.
- Requisitos: Acceso root, Linux moderno, conexión a internet para descargar dependencias.
- Resultado: Servicio funcional y estable, documentado paso a paso.
- Troubleshooting: Logs estándar en /var/log/, comandos de verificación al final de cada sección.
Qué es SC y por qué importa a un sysadmin Linux
El 30 de septiembre de 2026, los analistas de Sucuri publicaron el desglose de un backdoor de WordPress al que bautizaron como SC, por los marcadores SC_ que aparecen en el código inyectado. Lo que documentaron no es una variante más del malware de siempre: es una malla auto-curativa (self-healing mesh) que vive en al menos ocho ubicaciones a la vez y en la que cada componente puede reconstruir a todos los demás.
Si administras un servidor con WordPress, ya sea un blog personal, una intranet pequeña o un sitio de e-commerce sobre LAMP, esta clase de infección cambia las reglas. Limpiar los archivos visibles no alcanza. Lo que vuelve a aparecer después del borrado no es el mismo archivo: es una copia escrita por otro componente que sigue vivo. La próxima vez que el lector del blog o el carrito de WooCommerce devuelva un 200, la infección ya está restaurada.
Lo que hace a SC diferente es la combinación de tres elementos:
- Persistencia fuera del filesystem. Una copia del payload vive en una fila de la tabla
wp_optionsy, en servidores con soporte, en un segmento de memoria compartida System V. El primer request que pasa por el drop-in correcto reescribe todo el árbol de archivos. - Redundancia deliberada. El mismo plugin falso está en
wp-content/pluginsy enwp-content/mu-plugins; los dos drop-ins de carga temprana (db.phpyadvanced-cache.php), el bloque inyectado enfunctions.phpdel tema activo, y un loader disparado porauto_prepend_filemantienen copias y reglas de reinyección. - Canal de mando sobre infraestructura legítima. En vez de hablar con un dominio fijo, el payload consulta un smart contract en Ethereum a través de unos veinte gateways RPC públicos. Bloquear el dominio visto en el tráfico no interrumpe la comunicación.
El caso reportado por Sucuri no determina el vector inicial ni cuántas instalaciones están afectadas, pero la familia SC, según el analista Gabriel Barbosa, ilustra un patrón que los sysadmins Linux no deben subestimar: una infección de WordPress ya no es un problema de archivos, es un problema de sistema distribuido pequeño.
Las ocho ubicaciones del payload
Sucuri recuperó cada componente del backdoor en un compromiso distinto. El siguiente orden refleja el flujo de ejecución durante un request típico en WordPress, de más temprano a más tarde.
| # | Ubicación | Tipo | Qué hace | Cuándo se carga |
|---|---|---|---|---|
| 1 | .user.ini, php.ini o .htaccess |
Config | Define auto_prepend_file apuntando al loader #2. PHP lo cachea hasta 300 s. |
Antes de cada request PHP en el árbol |
| 2 | wp-content/c1b12371.php * |
Shim visible | Incluye el loader oculto #3 si existe. Si no, no hace nada: silencio cómplice. | Prepend del #1 |
| 3 | wp-content/.c1b12371.php * |
String-table loader | Reconstruye el plugin falso desde copias en plugins, cache, un ZIP o un segmento shm. Define la constante SC_AUTO_PREPEND. |
Inclusión por el shim |
| 4 | wp-content/db.php |
Drop-in bootstrap | Lleva el payload completo como blob gzip+base64. Lo descodifica y reescribe el plugin cuando desaparece. | Bootstrap temprano de WordPress |
| 5 | advanced-cache.php |
Drop-in aún más temprano | Busca el payload en cinco lugares independientes (mu-plugin, plugin, shm, ZIP, opción de la base de datos) y lo inyecta en plugins_loaded. |
Bootstrap si WP_CACHE está activo |
| 6 | wp-content/themes/<tema-activo>/functions.php |
Bloque inyectado | Bloque acotado entre marcadores al final de un functions.php legítimo. Es el gemelo de db.php: reescribe el plugin cuando falta. |
Casi cada request |
| 7 | wp-content/mu-plugins/hyper-engine-kit.php * |
Payload backdoor | Se filtra de la lista de plugins y de los chequeos de update. Habla con el C2, escanea el sitio, crea admin oculto, regenera la malla. | Autoload de mu-plugins |
| 8 | wp-content/plugins/hyper-engine-kit/hyper-engine-kit.php * |
Copia redundante | Idéntico al #7, con una página de ajustes creíble para parecer un plugin de caché. | Autoload normal de plugins |
* Los nombres de archivo varían entre sitios. c1b12371 y hyper-engine-kit son los observados en el caso de Sucuri.
Qué hace el backdoor, paso a paso
Una vez que el payload está cargado, ejecuta cuatro acciones que conviene entender porque cada una tiene un indicador que puedes buscar en logs y tablas.
Se esconde
Filtra la lista de plugins, el transient de actualizaciones y las vistas de plugins del sitio y la red para borrar su propia entrada. Emite además JavaScript en el admin que limpia la fila de la tabla como red de seguridad. El resultado: wp plugin list puede no mostrarlo, y un escaneo superficial va a pasarlo por alto.
Habla con el C2 por Ethereum
El payload lleva una lista de unos veinte gateways RPC públicos de Ethereum y selectores de métodos de smart contracts. En vez de consultar un dominio fijo, los consulta a través de servicios legítimos, lo que hace muy difícil bloquearlo solo por DNS o IP. Los selectores de método leen instrucciones del contrato; el reply puede ser:
- JavaScript para inyectar en el front-end (skimmers de checkout en tiendas WooCommerce).
- Código PHP para instalar.
- Listas de plugins de seguridad para desactivar y borrar, posiblemente reasignando o elevando otra cuenta antes.
Fingerprint, beacon y reescritura
Recolecta URL y host, versiones de WordPress y plugins, hashes de rutas, temas activos, lista de mu-plugins y tokens de sesión de administradores. Cifra el bundle y lo postea al endpoint resuelto. Con la respuesta actualiza la persistencia: reescribe db.php, advanced-cache.php, el bloque en functions.php, el loader y su .htaccess y .user.ini, el ZIP de restore, el segmento de memoria compartida y la fila de la base de datos. Abre incluso una conexión cruda a la base para insertar la opción de payload, sin pasar por la API de WordPress.
Crea un administrador oculto
O adopta uno existente o genera uno nuevo escribiendo directo en wp_users y wp_usermeta, con capacidades bajo la meta key por defecto. Luego lo oculta de la lista de usuarios, del conteo y de las vistas por rol, y falsifica cookies válidas de autenticación para esa cuenta. El operador entra sin contraseña. Variantes relacionadas usan triggers en MySQL que recrean al admin en cualquier INSERT, así que borrar la cuenta no alcanza hasta que se quite el trigger.
Dónde vive la persistencia fuera de disco
El error más común de cualquier sysadmin que se enfrenta a una reinfección es mirar solo /var/www. SC almacena el payload en tres lugares que sobreviven al borrado de archivos.
| Ubicación | Por qué sobrevive | Cómo se limpia |
|---|---|---|
Fila de wp_options con nombre aleatorio |
El blob gzip+base64 se lee por conexión directa. La próxima request a advanced-cache.php lo reescribe a disco. |
wp db query "DELETE FROM wp_options WHERE option_name LIKE 'sc_%'" + revisar filas con LENGTH(option_value) > 10000 |
| Segmento de memoria compartida System V | Está en RAM del servidor, no en disco. En hosting compartido puede pertenecer a otra cuenta del mismo servidor. | ipcrm -M <key> como root, o pedir al proveedor. Inofensivo si los drop-ins que lo leen ya están limpios. |
| Cron hooks de WordPress y tareas del cron del sistema | Se reejecutan en el siguiente wp-cron.php aunque el sitio esté sin tráfico. |
wp cron event list --allow-root + wp cron event delete <hook> para los hooks sospechosos |
Las variantes de SC vistas por Sucuri además usan triggers de MySQL para recrear al administrador en cualquier INSERT a la tabla wp_users. Esto es crítico: si limpiás archivos y la base, pero queda el trigger, el próximo registro vuelve a meter al admin escondido.
# Auditoría de triggers sospechosos
mysql -u root -p wordpress_db -e
"SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_STATEMENT
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = DATABASE();"
Indicadores de compromiso que puedes buscar hoy
Antes de tocar nada, un buen primer barrido es buscar los marcadores de SC en las rutas que menciona Sucuri. Estos comandos asumen el path estándar de Debian/Ubuntu, ajustá DOCROOT si usas otro layout.
DOCROOT=/var/www/html
# 1. Buscar prepends sospechosos
grep -rE 'auto_prepend_files*=' "$DOCROOT" --include='.user.ini' --include='php.ini' --include='.htaccess' 2>/dev/null
# 2. Detectar el shim y el loader oculto
ls -la "$DOCROOT/wp-content/".*.php "$DOCROOT/wp-content/"*.php 2>/dev/null | head -20
# 3. Marcadores SC_ en archivos PHP del sitio
grep -rlE 'SC_(AUTO_PREPEND|REBUILD|MARKER)' "$DOCROOT/wp-content" 2>/dev/null
# 4. Drop-ins modificados
ls -la "$DOCROOT/wp-content/db.php" "$DOCROOT/wp-content/advanced-cache.php" 2>/dev/null
# 5. Bloque inyectado en el tema activo
find "$DOCROOT/wp-content/themes" -maxdepth 2 -name functions.php
-exec grep -lE 'SC_AUTO_PREPEND|/* SC_BEGIN' {} ;
# 6. Plugin fantasma en mu-plugins
ls -la "$DOCROOT/wp-content/mu-plugins/" 2>/dev/null
Y en la base de datos, los indicadores son:
- Filas en
wp_optionscon nombre aleatorio yLENGTH(option_value) > 10000, especialmente si la columna empieza con la firma gzipx1fx8bx08en base64. - Prefijo
sc_en option_name y transients. - Triggers en
information_schema.TRIGGERSque apuntan awp_usersowp_usermeta. - Un administrador que no aparece en
wp-admin/users.phppero existe enwp_usersconwp_capabilitiespobladas.
# Detectar opciones sospechosas por tamaño y firma
wp db query "SELECT option_name, LENGTH(option_value) AS len
FROM wp_options
WHERE LENGTH(option_value) > 10000
ORDER BY len DESC LIMIT 20;" --allow-root
# Buscar prefijos sc_ en options y transients
wp db query "SELECT option_name FROM wp_options
WHERE option_name LIKE 'sc_%' OR option_name LIKE '%_sc_%' LIMIT 20;" --allow-root
# Listar cron hooks de WP para ver reescritores
wp cron event list --allow-root | grep -iE 'sc_|rebuild|persist'
Orden correcto de limpieza (no, no es borrar archivos)
Si borrás archivos en el orden equivocado, el siguiente request los restaura. El método que documenta Sucuri sigue la idea de cortar la ejecución primero, limpiar fuera de disco, después limpiar disco, todo en una sola pasada. El detalle está en el timing: PHP cachea auto_prepend_file hasta 300 segundos, así que si vaciás el target del prepend antes de quitar la directiva, el sitio se cae. Si quitás la directiva antes de vaciar el target, el shim sigue activo.
- Neutralizar el prepend. Reemplazar el contenido del archivo target con un stub inerte, después quitar la directiva de
.user.ini,php.iniy.htaccess. - Limpiar persistencia fuera de disco. Borrar la fila de
wp_optionscon el payload, purgar el segmento de shm conipcrm -M(con ayuda del proveedor en hosting compartido), y eliminar los hooks de cron y los triggers de MySQL. - Eliminar el administrador oculto. Borrar la cuenta cuya meta key de capabilities está poblada y limpiar la opción huérfana que apunta a su ID.
- Remover los archivos en una pasada. Borrar los loaders y el shim, las dos copias del plugin falso (mu-plugins y plugins), el ZIP de restore, y los drop-ins maliciosos. En el
functions.phpdel tema, recortar solo el bloque entre los marcadores, dejando intacto el resto del archivo. - Rotar credenciales y cerrar la entrada. Cambiar todas las contraseñas que pudieron haber sido expuestas, forzar logout de todas las sesiones, actualizar core, plugins y tema, y revisar el vector inicial: plugin vulnerable, tema nulled, credencial filtrada, backup expuesto.
El orden importa tanto como los comandos. Cualquier defensa que elimine un componente dejando vivo otro del que depende es un auto-ataque: le entrega al malware la excusa para regenerarse.
Qué cambia esto para tu WordPress en producción
Si tu sitio es un blog personal sobre LAMP en un VPS pequeño, el riesgo principal no es SC en sí: es que el patrón que documenta Sucuri (persistencia fuera de disco + C2 sobre infraestructura legítima + múltiples rutas de reinyección) se vuelva la norma. La conclusión operativa no es agregar otro plugin de seguridad, es revisar tres cosas que muchos sysadmins dan por hechas.
Auditoría periódica de wp_options, cron y triggers
El detalle clave de SC es que la persistencia vive en la base de datos y en tareas programadas, no en archivos. Una auditoría mensual corta es más útil que un escáner de malware diario: revisa opciones grandes, cron hooks y triggers con un comando como el del indicador 6 anterior. Es trabajo de cinco minutos que evita una limpieza de seis horas.
WAF con virtual patching
El vector inicial de este tipo de infecciones suele ser un plugin o tema con CVE conocida y sin parchar. Un WAF con virtual patching (Cloudflare, Sucuri, Wordfence con la regla correcta) bloquea el exploit antes de llegar a la aplicación. La diferencia entre un WAF activo y uno apagado es la diferencia entre un escaneo de reconocimiento en logs y un backdoor publicado en disco.
Visibilidad de salidas a gateways públicos
El truco del C2 sobre gateways RPC de Ethereum no es exclusivo de SC. Cualquier backdoor moderno habla con servicios legítimos abuseados como transporte: Cloudflare Workers, Netlify Edge, Vercel, IPFS gateways, WebDAV públicos. Si tu firewall solo bloquea destinos sospechosos, te lo vas a perder. Una regla que marque como interesante cualquier request saliente del usuario www-data hacia categorías como cryptocurrency, RPC o CDN reduce el ruido y deja ver el beacon cuando aparece.
SC es un caso particular, pero la lección es general. Un WordPress comprometido en 2026 ya no se parece a un archivo PHP malicioso suelto en /uploads. Se parece más a un servicio distribuido pequeño, con base de datos, memoria, tareas programadas y un canal de mando escondido entre servicios legítimos. La defensa tiene que dejar de mirar solo wp-content y empezar a mirar la base, el cron y el firewall de salida.
Resumen accionable para sysadmins
- Buscá los marcadores
SC_y los nombres de archivoc1b12371/hyper-engine-kitenwp-content; si aparecen, asumí compromiso y entrá al orden de limpieza, no al de “borrar lo obvio”. - Auditoría mensual de
wp_optionspor filas grandes con firma gzip+base64, de cron hooks y de triggers eninformation_schema.TRIGGERS. - WAF con virtual patching activo, no solo modo monitoreo. Un WAF en modo log es un logger caro.
- Reglas de firewall de salida que registren (no necesariamente bloqueen) tráfico del usuario del web server hacia gateways RPC, IPFS, Cloudflare Workers y similares.
- Si ya estás limpio, mantenete limpio: core, plugins y tema al día, backups probados y rotación de claves en cada incidente.
Preguntas frecuentes
¿Por qué Descubriendo SC: la amenaza persistente en WordPress para sysadmins Linux es relevante para sysadmins Linux?
Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.
¿Qué necesito para empezar con Descubriendo SC: la amenaza persistente?
Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.
¿Cuáles son los errores más comunes con Descubriendo SC: la amenaza persistente?
Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.
¿Cuándo usar Descubriendo SC: la amenaza persistente y cuándo una alternativa?
Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.
¿Cómo migro desde una configuración previa a Descubriendo SC: la amenaza persistente?
Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.
Lee también
- Guía Fedora 44: Novedades, Instalación y Upgrade para Sysadmins Linux
- Configura VLANs en Linux con nmcli: Guía paso a paso para sysadmins
- Protege tu SSH: Guía esencial para configurar Fail2ban en Linux
- Guía Definitiva: Configura Kubernetes con kubeadm en Ubuntu para Sysadmins Linux
- Configura Prometheus y Grafana: Guía DevOps para SysAdmins Linux
