En resumen: con disable_functions de PHP bloquea las funciones con las que PHP ejecuta comandos del sistema, como exec, shell_exec o proc_open. Eso dificulta al atacante el siguiente paso tras una intrusión. El ajuste solo funciona desde php.ini o desde el pool de FPM, debe adaptarse a la aplicación y no sustituye a la actualización.
Por qué disable_functions tiene sentido justo ahora
PHP2Shell trata de la ejecución remota de código malicioso sin autenticación. Las dos vulnerabilidades CVE-2026-109618 y CVE-2026-109619 residen en el propio intérprete de PHP, corregidas en PHP 8.5.12, 8.4.27, 8.3.36 y 8.2.35. La actualización es la única forma de cerrarlas.
El refuerzo actúa un nivel más tarde. Quien consigue ejecutar código en un servidor suele querer ir más allá: iniciar comandos del sistema, descargar herramientas, instalar una puerta trasera persistente. Muchos de estos pasos pasan por unas pocas funciones de PHP. Si están bloqueadas, el camino se vuelve más laborioso y más visible.
disable_functions no es, por tanto, un sustituto de los parches, sino una pieza para el caso de que, pese a todas las precauciones, algo se cuele. Eso vale tanto para futuras vulnerabilidades como para PHP2Shell.
Qué consigue disable_functions de PHP y qué no
El ajuste elimina las funciones indicadas del entorno de ejecución. Si un script llama a una función bloqueada, PHP se interrumpe con un error. El bloqueo vale para cualquier código que se ejecute en ese proceso de PHP, incluido el código introducido a escondidas.
Conviene conocer los límites:
- El ajuste no es un espacio de protección cerrado. Las extensiones de PHP, los fallos del intérprete o los programas externos a PHP pueden eludirlo.
- No impide que un atacante lea o escriba archivos a los que tiene acceso el usuario de PHP. De eso se encargan los permisos de archivos y el aislamiento.
- Solo funciona desde php.ini o como
php_admin_value. No se puede establecer conini_set(),.user.inini.htaccess.
disable_functions aporta más junto con un php.ini limpio, usuarios propios para cada sitio web y permisos de archivos restrictivos. Los fundamentos están en la guía Configurar php.ini de forma segura.
Qué funciones debería bloquear
Para los sitios web típicos que no necesitan comandos del sistema, la lista siguiente ha dado buen resultado. Incluye funciones para iniciar procesos y para controlar procesos en ejecución.
| Grupo | Funciones | Uso legítimo típico |
|---|---|---|
| Ejecutar comandos | exec, shell_exec, system, passthru |
Procesamiento de imágenes, copias de seguridad mediante script |
| Abrir procesos | proc_open, popen |
Composer, herramientas de PDF, envío de correo |
| Controlar procesos | proc_nice, proc_terminate, proc_get_status |
Colas, tareas en segundo plano |
| Gestión de procesos | pcntl_exec, pcntl_fork |
normalmente solo en la línea de comandos |
| Señales y permisos | posix_kill, posix_setuid |
raramente en el uso web |
Como configuración queda así:
; php.ini del modo de ejecución web, p. ej. /etc/php/8.3/fpm/php.ini
disable_functions = exec,shell_exec,system,passthru,proc_open,popen,proc_nice,proc_terminate,proc_get_status,pcntl_exec,pcntl_fork,posix_kill,posix_setuid
Si la lista no es válida para todos los sitios web del servidor, establézcala en cada pool de FPM. Tras recargar, compruebe qué lista rige realmente en ese pool:
; /etc/php/8.3/fpm/pool.d/meine-seite.conf (extracto)
php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,popen
Probar antes la aplicación: así evita caídas
Quien establece la lista sin comprobarla corre el riesgo de que de repente dejen de funcionar la reducción de imágenes, las facturas en PDF o el envío de correo. Por eso, busque antes en el código las funciones afectadas:
# ¿Dónde y con qué frecuencia se usan las funciones en el código?
grep -rnoE "\b(exec|shell_exec|system|passthru|proc_open|popen|pcntl_exec)\s*\(" /var/www/meine-seite --include="*.php" \
| cut -d: -f1 | sort | uniq -c | sort -rn | head -30
Las coincidencias no significan automáticamente que la función se necesite en producción. Muchas bibliotecas comprueban primero si una función está disponible y, si no, optan por otra vía. Lo decisivo es una prueba en un entorno de preproducción con todos los procesos importantes: pedido, factura, envío de formularios, subida de imágenes, tareas programadas.
Si una aplicación exige obligatoriamente alguna de estas funciones, consulte los requisitos del sistema del fabricante en su página oficial. A menudo la tarea puede trasladarse a un pool separado o a un script de línea de comandos al que no se pueda acceder por web.
Activar el ajuste y comprobar su efecto
Tras el cambio, PHP debe volver a leer la configuración. Después, compruebe el valor en el modo de ejecución de su sitio web, no en la línea de comandos:
sudo systemctl reload php8.3-fpm
php-fpm8.3 -i | grep "^disable_functions"
# Revisar en el registro de errores las llamadas a funciones bloqueadas
sudo grep -i "has been disabled" /var/log/php/*.log | tail -20
Los mensajes del registro de errores siguen siendo valiosos más adelante. Si de pronto aparecen allí llamadas a funciones bloqueadas que su aplicación no utiliza, puede indicar código introducido a escondidas. Cómo proceder entonces lo describe la guía Detectar y eliminar webshells.
Errores típicos al usar disable_functions
En la práctica, el refuerzo rara vez fracasa por la técnica, sino por pequeños detalles. Estos errores son especialmente frecuentes:
- Archivo equivocado: la lista figura solo en el php.ini de la línea de comandos, el sitio web se ejecuta con PHP-FPM y queda desprotegido.
- Sin reinicio: el archivo es correcto, pero los procesos en ejecución siguen trabajando con la configuración antigua.
- Bloqueo demasiado amplio: también se bloquean funciones como
ini_setomail, y procesos importantes se interrumpen sin que nadie lo note. Los fallos suelen detectarse días después, por ejemplo por la falta de confirmaciones de pedido. - Establecido una vez, nunca comprobado: tras una migración, un cambio de versión de PHP o una reinstalación desde el panel de hosting, la lista ha desaparecido.
- Falsa sensación de seguridad: el bloqueo se entiende como sustituto de las actualizaciones. Sin embargo, no cierra ninguna vulnerabilidad del intérprete.
Incluya por eso la comprobación del valor activo en su rutina tras cada actualización de PHP. Basta una mirada rápida, apenas lleva tiempo y evita que un refuerzo se pierda en silencio.
Con varios sitios web en un servidor: cree para cada sitio un pool propio con su propia lista. Como complemento, open_basedir limita los directorios a los que PHP puede acceder.
¿Cómo ayuda PHP SOS en concreto?
- Revisamos el código y los procesos de su aplicación para ver si usan funciones críticas.
- Definimos para cada sitio web una lista de bloqueo adecuada y la probamos antes de la puesta en producción.
- Combinamos el bloqueo con pools, permisos de archivos y registro en un concepto de refuerzo coherente.
- Documentamos los ajustes y vigilamos el registro de errores en busca de llamadas anómalas.
Cómo se desarrolla todo ello como paquete completo lo describe el servicio Refuerzo de servidores PHP.
Preguntas frecuentes
¿Puedo establecer disable_functions con ini_set() o .htaccess?
No. El ajuste solo funciona desde php.ini o como php_admin_value en el pool de FPM o en la configuración de Apache. No se puede establecer en tiempo de ejecución, y la aplicación tampoco puede volver a habilitar las funciones bloqueadas.
¿Protege disable_functions frente a PHP2Shell?
No. PHP2Shell afecta al propio intérprete de PHP y la vulnerabilidad solo se cierra con la actualización. Las funciones bloqueadas, sin embargo, pueden limitar el margen de maniobra de un atacante tras una explotación exitosa.
¿Por qué php -i muestra una lista distinta de la de mi sitio web?
La línea de comandos suele leer su propio php.ini. Para el sitio web cuenta la configuración de PHP-FPM, mod_php o LiteSpeed. Compruebe por tanto el valor en el modo de ejecución con el que funciona su sitio web.
¿Qué aplicaciones necesitan proc_open o exec?
Depende de la aplicación. Lo típico es el procesamiento de imágenes mediante programas externos, la generación de PDF, el envío de correo con sendmail o herramientas como Composer. Compruébelo en el código y en los requisitos del sistema del fabricante.