Situación actual: PHP2Shell. Dos vulnerabilidades críticas de PHP (CVSS 9.2) permiten ejecutar código malicioso sin autenticación. Parches desde el 21/10/2026.Qué hacer ahora →

Usar disable_functions de PHP correctamente

Con disable_functions bloquea funciones de PHP arriesgadas. Cómo definir la lista según su aplicación sin dejar el sitio web fuera de servicio.

Actualizado 6 min de lecturaGuías

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 con ini_set(), .user.ini ni .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_set o mail, 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.

Consejo

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.

Fuentes

Contacto inmediato

Cada hora cuenta. Escríbanos ahora.

Describa brevemente el sistema, la versión de PHP y lo que ha observado. Nos pondremos en contacto, aclararemos la situación y trabajaremos en remoto hasta que el incidente quede cerrado y documentado.

Ayuda inmediata