Actualización (06/04/2026): Noticias críticas sobre web shells y campañas de malware activas.

  • Shells sofisticadas con persistencia cron: Microsoft reportó PHP web shells usando cookies como canales de control y cron jobs para auto-repararse en servidores Linux, eludiendo detección tradicional (02/04/2026).
  • Campaña Sign1 en escala: Sucuri detectó 39.000+ sitios WordPress comprometidos por inyección de JavaScript vía shells, usando ofuscación basada en tiempo para evitar análisis (28/03/2026).
  • CVEs de Object Injection en plugins: Nuevas vulnerabilidades CVE-2026-2599 y CVE-2026-2471 permiten RCE vía Object Injection en plugins populares de manejo de datos, vector directo para upload de shells.

Los web shells PHP son archivos maliciosos que un atacante sube a tu servidor para tener acceso remoto y persistente al sistema. Desde ahí puede ejecutar comandos, borrar o modificar contenido, plantar más malware, o usartu servidor como base para atacar otros sitios. La mayoría son tan simples que caben en unas pocas líneas de código (si, otro plugin vulnerable), pero así y todo pasan desapercibidas durante meses porque la gente no revisa wp-content/uploads regularmente. En este artículo vemos qué son exactamente, cómo los hackers las usan, y por qué tu firewall del hosting no las detecta aunque creas que está haciendo su trabajo.

En 30 segundos

  • Un web shell PHP es un script que permite ejecutar comandos en tu servidor desde el navegador, con los permisos del usuario www-data
  • Suelen entrar por formularios vulnerables, upload sin validación, o LFI/RFI en plugins desactualizados
  • Una vez adentro, un atacante puede listar archivos, modificar código, robar credenciales de base de datos, o instalar backdoors más complejas
  • Las más peligrosas se camuflan: tienen nombres como index.php, .jpg, o usan ofuscación y encoding para evitar detección antimalware
  • Detectarlas requiere revisar timestamps de archivos, buscar patrones de código, y monitorear actividad sospechosa en los logs

Sucuri Es una plataforma de seguridad web desarrollada para detectar, prevenir y remover malware, ataques DDoS y vulnerabilidades en sitios WordPress y otros CMS. Ofrece monitoreo continuo, firewall de aplicaciones web (WAF) y servicios de limpieza de infecciones.

Qué es un web shell PHP

Un web shell PHP es un script malicioso que corre en el servidor y te deja ejecutar comandos remotamente. Lo más básico es un archivo PHP que recibe un parámetro por GET o POST, lo pasa a exec() o system(), y devuelve la salida en pantalla. Ponele que un atacante sube un archivo llamado admin.php con este código:

<?php system($_GET['cmd']); ?>

Ya está. Ahora puede ir a tu sitio y hacer tudominio.com/wp-content/uploads/admin.php?cmd=ls%20-la y ve la estructura de directorios. O cmd=cat%20wp-config.php y roba las credenciales de la base de datos. O instala un panel de control más sofisticado. Algunos atacantes son perezosos y dejan shells así de simples. Otros trabajan más: ofuscan el código con base64, lo ponen en comentarios de HTML, lo llaman algo que parezca legítimo, o lo hacen polimórfico para que cada scanning encuentre una firma diferente.

Características técnicas de web shells en PHP

Las variaciones que ves en la práctica son amplias, pero todas comparten ciertas características. Veamos cómo funcionan por dentro.

Ejecución de comandos

El corazón de cualquier web shell es una función que ejecuta comandos del sistema. Las más comunes son system(), exec(), shell_exec(), passthru(), y proc_open(). Cada una devuelve la salida de forma ligeramente diferente, pero todas hacen lo mismo: corren lo que el atacante le pasa. Si tu servidor tiene esas funciones deshabilitadas en php.ini (en la directiva disable_functions), el web shell no va a poder ejecutar comandos directamente. Pero un atacante inteligente sabe eso y busca alternativas: puede usar popen(), fopen() con un stream pipe, o incluso eval() + JavaScript ejecutado via Node.js si está disponible. Esto se conecta con lo que analizamos en niveles de seguridad en capas.

Enmascaramiento y ofuscación

La mayoría de shells no están escritas de forma legible. Algunos trucos que ves frecuentemente: Lo explicamos a fondo en estrategias de seguridad en profundidad.

  • Base64 encoding: todo el payload está codificado en base64, y se decodifica en tiempo de ejecución con base64_decode()
  • Nombres engañosos: index.php, .htaccess, style.css.php, o números aleatorios para parecer parte del sitio legítimo
  • Distribución en múltiples archivos: el código real está en un include que se carga desde otro directorio, no siempre bajo wp-content
  • Variables con ofuscación: usan variables con nombres crípticos, o eval() con strings construidos dinámicamente
  • Comentarios en idiomas extraños: meten comentarios chinos, rusos o árabe para que herramientas de escaneo automático no toquen el código

Persistencia y reinfección

Un atacante no pone un solo web shell. (Ojo: si encontraste uno, hay probabilidad alta de que haya otros escondidos.) Suele instalar varios con diferentes nombres, diferentes ubicaciones, diferentes mecanismos de acceso. Algunos shells inteligentes verifican que el atacante sigue siendo el propietario del servidor, y si detectan que la shell fue borrada, automáticamente se reinstala desde un payload guardado en la base de datos o en un archivo oculto en el servidor. Es como un rootkit para WordPress.

Vectores de ataque: cómo llegan los web shells

Ahora viene la pregunta práctica: ¿cómo entra un web shell a tu servidor en primer lugar? Los vectores principales son estos.

Upload sin validación en formularios

Es el vector clásico. Un plugin permite a usuarios subir archivos (contacto, galería, directorio de miembros) pero no valida la extensión, el tipo MIME, o el contenido real del archivo. Un atacante simplemente renombra su web shell shell.php como shell.jpg, lo sube, y algunos servidores configurados sin cuidado permiten ejecutar PHP incluso en directorios de upload. (El .htaccess que trae WordPress por defecto previene esto, pero si tu hosting sobrescribió la config o el plugin borró el .htaccess, estás expuesto.)

Local File Inclusion (LFI) y Remote File Inclusion (RFI)

Un plugin vulnerable a LFI deja al atacante incluir archivos locales. Ponele que hay un parámetro page=../../etc/passwd. Con un poco de ingeniería, puede incluir un archivo que él mismo subió con un nombre predecible. O con RFI (si está habilitada en php.ini), directamente carga PHP desde su propio servidor. Los plugins como TimThumb, File Manager, o viejos constructores de pages fueron campo fértil para esto. Sobre eso hablamos en plugins de seguridad para WordPress.

SQL Injection en la base de datos

Un atacante con acceso a la base de datos de WordPress puede usar LOAD_FILE() para escribir archivos en el servidor, o puede actualizar la opción template o template_root en wp_options para apuntar a un directorio donde él tiene control. Si tu base está comprometida, el web shell es lo de menos.

Explotación de núcleo WordPress desactualizado

Cuando WordPress tiene un CVE sin parchar, los escáneres automáticos lo detectan en minutos. Una de las vulnerabilidades más graves fue la arbitraria file upload en versiones viejas (CVE-2018-12895, por ejemplo). Los bots de ataque automático atienden eso inmediatamente.

Credenciales de FTP/SFTP o acceso al panel de hosting

Si tu contraseña de FTP está débil, o si el password del hosting fue roto por fuerza bruta, el atacante entra directo sin tocar WordPress. Simplemente coloca un .php en el directorio raíz o en wp-content/uploads, y listo. Complementá con amenazas amplificadas tras una intrusión.

Ejemplos reales de web shells PHP en sitios WordPress

Según reportes de Sucuri, las web shells más frecuentes encontradas en sitios WordPress tienen patrones reconocibles. Una de las más antiguas y todavía activa es la shell C99, que funciona como un gestor de archivos completo: lista directorios, edita código, ejecuta comandos, y tiene una interfaz web bastante amigable para el atacante. Otra muy común es PHPShell, más minimalista pero igualmente funcional. En 2024-2025, vemos mucha actividad de shells ofuscadas con encoding, especialmente shells basadas en eval() que decodifican bloques de código en tiempo de ejecución. La ventaja para el atacante es que un simple grep por system( no la encuentra.

Hace poco me tocó auditar un sitio donde encontramos una shell llamada .wp-cache/wp-cache.php — parecía un archivo legítimo del plugin WP Super Cache, pero tenía una línea que incluía un archivo desde un servidor remoto. El atacante había entrado meses antes por una vulnerabilidad en un plugin de formularios, y simplemente se quedó ahí, descargando updates maliciosas cada cierto tiempo. El sitio estaba infectando a visitantes con malware bancario. (Que no es poco para un CVSS de 9.8.)

Errores comunes en seguridad de uploads

1. Confiar en la extensión del archivo para validar tipo

Es lo primero que hace un desarrollador novato: valida que el archivo termine en .jpg o .png y lo da por seguro. Un atacante renombra su shell a .jpg.php, o usa un null byte shell.php%00.jpg (viejo pero ocasionalmente funciona), o carga un .htaccess que ordena ejecutar .jpg como PHP. La validación correcta incluye revisar el MIME type, los headers del archivo (magic bytes), y hasta ejecutar un análisis del contenido. Más contexto en importancia de mantener sistemas actualizados.

2. Permitir upload a directorios ejecutables

Si tu servidor está configurado para ejecutar PHP en wp-content/uploads, tenés un problema. WordPress incluye un .htaccess que lo previene, pero algunos hostings lo quitan, o permiten que sea reescrito por el usuario. Solución: coloca archivos de configuración adicionales, o mejor aún, guarda los uploads fuera de la raíz web (en una carpeta arriba) y sirve el contenido a través de PHP que valida acceso.

3. No revisar los uploads después de comprometer el sitio

Muchos admins actualizan WordPress, parquean los plugins vulnerables, y creen que zafó. Pero nunca revisan wp-content/uploads. Y ahí está: el web shell del atacante anterior esperando pacientemente. Si tu sitio fue hackeado una vez, cualquier directorio de upload es sospechoso hasta demostrar lo contrario.

Cómo detectar web shells en tu sitio

Detectar shells requiere ir más allá de un simple escaneo antimalware (que puede fallarle a shells ofuscadas). Acá van las técnicas que funcionan.

Búsqueda de patrones de código

Grep por las funciones de ejecución de comandos:
grep -r "system(" wp-content/uploads/
grep -r "exec(" wp-content/uploads/
grep -r "shell_exec(" wp-content/uploads/
grep -r "passthru(" wp-content/uploads/

Si el resultado tiene algo que no sea un plugin o tema conocido, revisá manualmente ese archivo. Muchas shells se disfrazan de comentarios o strings, así que también busca variantes ofuscadas:

grep -r "base64_decode" wp-content/uploads/
grep -r "eval(" wp-content/uploads/
grep -r "create_function(" wp-content/uploads/ Lo explicamos a fondo en cadena de suministro y CI/CD.

Análisis de timestamps y permisos

Revisa cuándo se modificaron los archivos en wp-content/uploads. Los uploads legítimos tienen timestamps recientes pero predecibles. Si hay un .php cuyamarca es de hace 6 meses pero el último upload legítimo fue hace 1 mes, es sospechoso. O si los permisos están en 777 cuando deberían estar en 644. Los atacantes a veces cambian permisos para que el web shell sea escribible, facilitando reinfecciones. Más contexto en impacto en funcionalidades del negocio.

Monitoreo de procesos y conexiones de red

Si tenés acceso SSH a tu servidor, ejecutá
netstat -tulpn | grep ESTABLISHED
para ver conexiones activas. Una shell que está siendo usada va a tener conexiones remotas hacia el atacante. O usa ps aux para listar procesos y buscar algo fuera de lo normal (un server Node.js no esperado, un curl haciendo requests, un Apache ejecutando comandos extraños).

Esto se conecta con Expandir con: [«Web Shells en PHP: Características y Vectore, donde cubrimos el tema en profundidad.

Escaneo automático con herramientas

Wordfence detecta shells conocidas, pero si la shell está ofuscada con una firma que Wordfence no conoce, va a pasar desapercibida. Patchstack también hace búsqueda de patrones. Pero la herramienta más completa es ShellDetect, que usa análisis estático y patrones heurísticos para encontrar shells incluso ofuscadas. Dicho esto, una revisión manual siempre va a encontrar cosas que las herramientas se pierden.

Preguntas Frecuentes

¿Qué tan fácil es crear un web shell PHP?

Demasiado fácil. Un principiante puede crear una en minutos. Por eso los atacantes automáticos las despliegan masivamente: instalan cientos en sitios vulnerables a ver cuál se queda activa. La mayoría son detectadas y borradas, pero basta que una persista para que tengan acceso total al servidor.

¿Mi antimalware del hosting previene web shells?

Parcialmente. Detecta las signatures conocidas, pero si el shell usa ofuscación nueva o es custom, es probable que pase. Además, el antimalware del hosting suele escanear una vez al día o menos. Durante esas 24 horas, un atacante puede tener acceso total. No es suficiente confiar solo en eso.

¿Qué hago si encontré una shell en mi sitio?

Primero, no la borres sin investigar. Documenta el nombre, la ubicación, la fecha de creación, y su contenido completo. Luego: (1) cambia TODAS tus contraseñas (WordPress, FTP, hosting, bases de datos), (2) revisa los logs de acceso web y SSH para ver cuándo entró el atacante y qué hizo, (3) busca otras shells o backdoors, (4) actualiza WordPress, plugins y temas a las versiones más nuevas, (5) borra las shells, (6) configura un Web Application Firewall como Wordfence o Cloudflare para bloquear patrones conocidos. Si sospechas que la base de datos fue comprometida, considera reescribir la contraseña de WordPress en la base de datos manualmente.

¿Hay web shells que no usen funciones de ejecución de comandos?

Sí, pero son menos comunes. Algunos shells usan assert() o create_function() para ejecutar código dinámico. Otros manipulan directamente el sistema de archivos con fopen() y fwrite() para crear archivos maliciosos en ubicaciones estratégicas. Lo importante es que si el atacante puede escribir o modificar archivos, eventualmente va a poder ejecutar código.

Conclusión

Los web shells PHP son la puerta trasera más simple y efectiva para un atacante. La mayoría entra por formularios sin validación o plugins desactualizados, se esconden con nombres falsos u ofuscación, y pueden estar meses en tu servidor sin que lo notes. La detección requiere diligencia: revisar timestamps, buscar patrones de código, monitorear logs, y auditar directorios de upload regularmente. Si mantienes WordPress, plugins y temas actualizados, validás todos los uploads, deshabilitas funciones de ejecución en php.ini cuando puedas, y configurás un WAF como Wordfence, reducís drásticamente el riesgo. Pero si tu sitio fue hackeado alguna vez, asume que hay shells escondidas hasta demostrar lo contrario. No es paranoia, es experiencia.

Fuentes

Categorizado en: