"sh -c /usr/sbin/sendmail -t -i", propietario www-data. Encontré esa línea en un listado de procesos la semana pasada y me pasé mis buenos cuatro minutos con el pulso acelerado hasta que recordé que la función mail() de PHP hace exactamente eso, cada vez, por diseño. Esa falsa alarma es, en el fondo, toda la columna. Desde el 21 de octubre todos estamos parcheando CVE-2026-109618 y CVE-2026-109619, la pareja que ya todo el mundo llama php2shell, y los análisis de la comunidad sobre cómo detectarlos chocan siempre contra el mismo muro: el exploit en sí es un fallo de memoria que se dispara antes de que se ejecute el código de tu aplicación, así que tus logs no muestran nada. Lo único que puedes pillar es lo que viene después. Y lo que viene después solo llama la atención si tu usuario web es normalmente aburrido.

Así que mi argumento va de arquitectura, no de reglas de alerta. Si www-data lanza shells con regularidad, escribe ficheros .php en el document root y ejecuta tareas de cron, ninguna regla de detección que escriba nadie va a distinguir a un atacante de un martes cualquiera en tu servidor. Las reglas solo pueden ser tan finas como silenciosa sea tu línea base. Un usuario web que nunca ejecuta nada y nunca escribe código te da una señal de la que te puedes fiar de verdad. Uno que hace ambas cosas cada vez que a un plugin le apetece te da un panel lleno de alertas de nivel 8 que todo el mundo habrá aprendido a ignorar para el jueves.

Recuerda lo grave que es esta. CVSS v4.0 9.2, sin autenticación, y afecta por igual a PHP-FPM, mod_php, php-cgi, FrankenPHP y LiteSpeed, con mod_php como el peor caso porque el atacante entra antes de que tu router llegue a cargarse. Las versiones corregidas son 8.5.12, 8.4.27, 8.3.36 y 8.2.35. Cualquier cosa en 8.1 o anterior no tiene parche oficial, y los usuarios de Debian bullseye atascados en PHP 7.4 tampoco recibieron nada. Cuando salió el aviso, el feed de vulnerabilidades de Wazuh aún no conocía ninguno de los dos CVE, CISA KEV todavía no los había incluido y la única prueba de concepto que circulaba no estaba verificada y quizá venía con trampa. Durante unos días, muchos equipos se defendieron de algo que sus escáneres ni siquiera sabían nombrar.

La objeción más fuerte merece una respuesta directa, porque tiene razón. Las aplicaciones PHP reales hacen estas cosas a propósito. WordPress se actualiza a sí mismo escribiendo PHP en su propio árbol. La mitad de los CMS que he mantenido ejecutan tareas programadas como el usuario web porque en 2014 era lo más cómodo. mail() lanza una shell. Decirle a una agencia pequeña con cuarenta webs de clientes que lo rehaga todo en plena emergencia es pura fantasía, y no voy a fingir lo contrario. Los partidarios de priorizar la detección también tienen su parte de razón: no puedes rediseñar en mitad del incendio, así que vigilas lo que tienes y aceptas el ruido.

Aun así, me quedo en el otro lado, y te explico por qué. Cada una de esas costumbres es algo que puedes abandonar a un precio conocido y finito. Envía el correo por SMTP con una librería y mail() no volverá a hacer fork nunca más. Lanza las actualizaciones desde un usuario de despliegue a través de tu pipeline y deja el document root en solo lectura para el proceso que lo sirve. Pasa el cron a su propia cuenta. Nada de esto es exótico, y una vez hecho, un muestreo de la lista de procesos o un vigilante de integridad de ficheros pasa de ser una pista ruidosa a una alarma casi segura. Un muestreo cada 60 segundos siempre se va a perder un curl que vive dos segundos. Pero en una cuenta silenciosa basta con un solo acierto, porque ahí no debería haber nada en absoluto.

Una cosa más que no tiene nada que ver con la detección ingeniosa: un paquete parcheado no parchea los workers de php-fpm que ya están en marcha. Este mes he visto dos servidores en 8.3.36 según apt y todavía con el binario vulnerable según la realidad, porque nadie reinició el pool. Es el fallo más PHP que se puede imaginar, la verdad: nuestro modelo shared-nothing lo perdona casi todo, salvo el proceso maestro que lleva levantado desde agosto. Reinícialo. Y luego comprueba que de verdad lo hiciste.

Para los rezagados de la 7.4 a la 8.1, lo honesto es sacarlos de la internet pública, no montarles monitorización alrededor y llamarlo cobertura. Vigilar una puerta que sabes que no puedes cerrar sirve, como mucho, una semana. A partir de ahí no es más que un plan para enterarte del compromiso un poco antes.

Así que esto es lo que de verdad me gustaría que me contaras, porque sospecho que las respuestas se dividen entre agencias y empresas de producto: hoy, en tus servidores de producción, ¿puede el usuario que sirve PHP escribir en el directorio desde el que sirve? Y si puede, ¿cuál es la funcionalidad concreta que perderías al quitarle ese permiso, y compensa ese punto ciego del tamaño de php2shell?