Em resumo: com o PHP disable_functions bloqueia as funções através das quais o PHP executa comandos de sistema, como exec, shell_exec ou proc_open. Isto dificulta o passo seguinte aos atacantes após uma intrusão. A definição só produz efeito a partir do php.ini ou do pool FPM, tem de se ajustar à aplicação e não substitui uma atualização.
Porque é que o disable_functions faz sentido precisamente agora
No PHP2Shell trata-se da execução remota de código malicioso sem autenticação. As duas vulnerabilidades CVE-2026-109618 e CVE-2026-109619 estão no próprio interpretador PHP, corrigidas no PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35. A atualização é a única forma de as fechar.
O reforço de segurança atua um nível mais tarde. Quem consegue executar código num servidor quer, em regra, ir mais longe: iniciar comandos de sistema, descarregar ferramentas, instalar uma backdoor persistente. Muitos destes passos passam por poucas funções PHP. Se estiverem bloqueadas, o caminho torna-se mais penoso e mais visível.
O disable_functions não é, por isso, um substituto dos patches, mas um elemento para o caso de algo passar apesar de todo o cuidado. Isto vale tanto para vulnerabilidades futuras como para o PHP2Shell.
O que o PHP disable_functions consegue e o que não consegue
A definição remove as funções indicadas do ambiente de execução. Se um script chamar uma função bloqueada, o PHP termina com um erro. O bloqueio vale para todo o código que corre neste processo PHP, ou seja, também para código introduzido.
Deve conhecer os limites:
- A definição não é um espaço protegido fechado. Extensões PHP, erros no interpretador ou programas fora do PHP podem contorná-la.
- Não impede que um atacante leia ou escreva ficheiros a que o utilizador PHP tem acesso. Para isso servem as permissões de ficheiros e o isolamento.
- Só produz efeito a partir do php.ini ou como
php_admin_value. Comini_set(),.user.iniou.htaccessnão pode ser definida.
O disable_functions rende mais em conjunto com um php.ini bem configurado, utilizadores próprios por site e permissões de ficheiros restritivas. Os fundamentos estão no guia Configurar o php.ini com segurança.
Que funções deve bloquear
Para sites típicos sem necessidade de comandos de sistema, a lista seguinte tem-se revelado eficaz. Abrange funções para iniciar processos e para controlar processos em execução.
| Grupo | Funções | Uso legítimo típico |
|---|---|---|
| Executar comandos | exec, shell_exec, system, passthru |
Tratamento de imagens, cópias de segurança por script |
| Abrir processos | proc_open, popen |
Composer, ferramentas de PDF, envio de e-mail |
| Controlar processos | proc_nice, proc_terminate, proc_get_status |
Filas de espera, tarefas em segundo plano |
| Gestão de processos | pcntl_exec, pcntl_fork |
geralmente só na linha de comandos |
| Sinais e permissões | posix_kill, posix_setuid |
raramente em operação web |
Como configuração, fica assim:
; php.ini do modo de operação web, p. ex. /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
Se a lista não valer para todos os sites do servidor, defina-a por pool FPM. Depois de recarregar, verifique que lista vale realmente nesse pool:
; /etc/php/8.3/fpm/pool.d/meine-seite.conf (excerto)
php_admin_value[disable_functions] = exec,shell_exec,system,passthru,proc_open,popen
Verificar antes a aplicação: como evitar falhas
Quem define a lista sem verificar arrisca que a redução de imagens, as faturas em PDF ou o envio de e-mail deixem de funcionar de repente. Por isso, procure antes no código as funções em causa:
# Onde e quantas vezes são usadas as funções no 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
Os resultados não significam automaticamente que a função seja necessária em operação. Muitas bibliotecas verificam primeiro se uma função está disponível e, caso contrário, recorrem a alternativas. Decisivo é um teste num ambiente de staging com todos os processos importantes: encomenda, fatura, envio de formulários, upload de imagens, tarefas agendadas.
Se uma aplicação exigir obrigatoriamente uma destas funções, verifique os requisitos de sistema do fabricante na sua página oficial. Muitas vezes a tarefa pode ser transferida para um pool separado ou para um script de linha de comandos que não seja acessível pela web.
Ativar a definição e controlar o efeito
Depois da alteração, o PHP tem de voltar a ler a configuração. Verifique depois o valor no modo de operação do seu site, não na linha de comandos:
sudo systemctl reload php8.3-fpm
php-fpm8.3 -i | grep "^disable_functions"
# Verificar no registo de erros as chamadas a funções bloqueadas
sudo grep -i "has been disabled" /var/log/php/*.log | tail -20
As mensagens do registo de erros são valiosas também mais tarde. Se aparecerem de repente chamadas a funções bloqueadas, embora a sua aplicação não as use, isso pode indicar código introduzido. Como proceder nesse caso, descreve-o o guia Detetar e remover webshells.
Erros típicos na utilização do disable_functions
Na prática, o reforço de segurança raramente falha por razões técnicas, mas por pormenores. Estes erros são especialmente comuns:
- Ficheiro errado alterado: a lista está apenas no php.ini da linha de comandos, o site corre através do PHP-FPM e fica desprotegido.
- Sem reinício: o ficheiro está correto, mas os processos em execução ainda trabalham com a configuração antiga.
- Bloqueio demasiado amplo: funções como
ini_setoumailsão bloqueadas também, e processos importantes falham sem se notar. Os erros só são notados muitas vezes dias depois, por exemplo com confirmações de encomenda que não chegam. - Definido uma vez, nunca verificado: após uma mudança, uma troca de versão do PHP ou uma reinstalação através do painel de alojamento, a lista desapareceu.
- Falsa sensação de segurança: o bloqueio é entendido como substituto das atualizações. Mas não fecha nenhuma vulnerabilidade no interpretador.
Inclua por isso a verificação do valor ativo na sua rotina após cada atualização do PHP. Basta uma olhadela, custa pouco tempo e evita que um reforço de segurança se perca em silêncio.
Com vários sites num servidor: crie para cada site um pool próprio com lista própria. Em complemento, o open_basedir limita as pastas a que o PHP pode aceder.
Como ajuda concretamente a PHP SOS?
- Verificamos o código e os processos da sua aplicação quanto ao uso de funções críticas.
- Definimos para cada site uma lista de bloqueio adequada e testamo-la antes da entrada em produção.
- Combinamos o bloqueio com pools, permissões de ficheiros e registo num conceito de reforço coerente.
- Documentamos as definições e monitorizamos o registo de erros quanto a chamadas suspeitas.
Como isto decorre como pacote completo, descreve-o o serviço Reforço de segurança de servidores PHP.
Perguntas frequentes
Posso definir o disable_functions com ini_set() ou .htaccess?
Não. A definição só produz efeito a partir do php.ini ou como php_admin_value no pool FPM ou na configuração do Apache. Não pode ser definida durante a execução, e a aplicação também não pode voltar a libertar funções bloqueadas.
O disable_functions protege contra o PHP2Shell?
Não. O PHP2Shell afeta o próprio interpretador PHP; a vulnerabilidade só se fecha com a atualização. As funções bloqueadas podem, porém, limitar a margem de manobra de um atacante após uma exploração bem-sucedida.
Porque é que o php -i mostra uma lista diferente da do meu site?
A linha de comandos lê muitas vezes um php.ini próprio. Para o site conta a configuração do PHP-FPM, do mod_php ou do LiteSpeed. Por isso, verifique o valor no modo de operação através do qual o seu site corre.
Que aplicações precisam de proc_open ou exec?
Depende da aplicação. Típicos são o tratamento de imagens através de programas externos, a geração de PDF, o envio de e-mail via sendmail ou ferramentas como o Composer. Verifique-o no código e nos requisitos de sistema do fabricante.