Em resumo: Para admins sem formação em programação bastam cinco noções para operar o PHP em segurança: o PHP é composto por vários programas (linha de comandos, PHP-FPM, módulo Apache), cada um com a sua versão; as definições atuam em níveis, do php.ini à aplicação; o PHP-FPM distribui os pedidos por workers em pools; uma atualização só produz efeito depois de reiniciados todos os processos; e os registos são a indicação mais importante quando algo não está bem. Quem conhece estes pontos consegue fechar vulnerabilidades como o PHP2Shell com rapidez e de forma comprovável.
De que é composto o PHP num servidor
O PHP não é um programa único. Num servidor Linux típico encontram-se várias variantes, cada uma ligada através de uma interface de servidor (SAPI):
| Variante | Nome típico | Para quê |
|---|---|---|
| Linha de comandos (CLI) | php, php8.3 |
cronjobs, Composer, scripts de manutenção |
| PHP-FPM | php-fpm, php-fpm8.3 |
pedidos web atrás do Nginx ou do Apache |
| Módulo Apache | mod_php, libphp |
pedidos web diretamente no processo do Apache |
| CGI | php-cgi |
estruturas mais antigas |
Cada variante pode ter uma versão diferente e um php.ini diferente. Em muitos servidores correm ainda várias versões do PHP em paralelo, por exemplo o 8.2 e o 8.4. Numa atualização, cada uma tem de ser considerada individualmente. Como funcionam as interfaces explica-o PHP-FPM explicado.
A variante que realmente serve os seus sites descobre-se através dos processos em execução e da configuração do servidor web:
ps -eo pid,user,lstart,cmd | grep -E "php|httpd|apache2" | grep -v grep
apachectl -M 2>/dev/null | grep -i php # o Apache carrega um módulo PHP?
ls /run/php/ 2>/dev/null # sockets FPM, muitas vezes por versão e pool
A coluna com a hora de arranque é importante mais tarde, no reinício: todos os processos PHP têm de ter sido iniciados depois do momento da atualização. Se os processos correm sob utilizadores diferentes, isso indica pools separados, o que é bom. Se aparecer um módulo PHP no Apache, embora todos os sites devam correr por FPM, é sinal de um legado que deve ser removido. Para interfaces de alojamento como o Plesk ou o cPanel vale o mesmo princípio, só que a interface mostra as versões e os handlers por site; decisivo continua a ser o que realmente corre como processo.
Os comandos mais importantes para admins
php -v # versão da linha de comandos
php --ini # php.ini carregado e diretórios lidos adicionalmente
php --ini=diff # a partir do PHP 8.5: desvios da predefinição
php -m # módulos compilados e carregados
php --ri session # definições de uma extensão
php -l datei.php # verificação de sintaxe sem execução
php-fpm8.3 -v # versão do binário FPM (nome consoante a distribuição)
php-fpm8.3 -t # testar a configuração FPM sem reiniciar
systemctl status php8.3-fpm
Duas notas do manual: o php -l encontra erros de sintaxe, mas não erros que só surgem na execução. E o php -i chama o phpinfo(); a saída não pertence a ficheiros públicos no diretório web.
Como as definições do PHP atuam
Uma definição pode ser feita em vários pontos. Quem pode alterar o quê, onde, é regulado pelo modo de alteração de cada diretiva:
- php.ini e conf.d: configuração de base por variante, lida no arranque.
- Pool FPM:
php_valueephp_admin_valuepor pool. Os valores definidos comphp_admin_valuenão podem, segundo o manual, ser sobrepostos pela aplicação comini_set(). - Nível de diretório:
.user.inino FPM ou.htaccessno mod_php, apenas para diretivas no modoINI_PERDIRouINI_ALL. - Aplicação:
ini_set()em tempo de execução, apenas para diretivas no modoINI_ALL.
Um exemplo: o memory_limit tem o modo INI_ALL, pode portanto ser alterado pela aplicação. O post_max_size tem INI_PERDIR e não pode ser alterado com ini_set(). Por isso, o php.net exige, nas medidas provisórias do PHP2Shell, definir os valores de modo a que as aplicações não os possam sobrepor. Os detalhes sobre os níveis explica-os O php.ini explicado.
Pools PHP-FPM em resumo
Um pool é um grupo de workers com utilizador próprio, socket próprio e definições próprias. As diretivas mais importantes segundo o manual:
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
pm = dynamic ; static, dynamic ou ondemand
pm.max_children = 20 ; no máximo 20 pedidos em simultâneo
pm.max_requests = 500 ; renovar o worker após 500 pedidos
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/shop-slow.log
php_admin_value[error_log] = /var/log/php-fpm/shop-error.log
php_admin_flag[log_errors] = on
Um pool próprio por site, com utilizador próprio, separa os sites uns dos outros. O security.limit_extensions está por predefinição em .php .phar e impede o FPM de executar extensões de ficheiro que não sejam PHP. O clear_env está por predefinição ativado e mantém as variáveis de ambiente afastadas do worker.
Registos: onde os admins devem olhar
O PHP escreve os erros no destino definido por error_log, o PHP-FPM também no seu próprio registo e, nos pedidos lentos, no slowlog com backtrace. A isto juntam-se os registos de acesso e de erros do servidor web. Certifique-se de que o display_errors está desativado em produção e o log_errors ativado: os erros pertencem ao registo, não à página web. Os registos devem ainda ser rodados e conservados durante um período definido, para que ainda existam em caso de emergência. Depois do PHP2Shell, a imprensa especializada recomenda conservar os registos do servidor a partir de 20/10/2026. Um forte sinal de alerta é um processo PHP-FPM ou do servidor web que inicia uma shell; como o reconhecer está em Sinal de alerta: o servidor web inicia uma shell.
Lista de verificação para admins após o PHP2Shell
- Listar todas as variantes e versões do PHP no servidor, também as não utilizadas.
- Verificar o estado dos pacotes; em backports da distribuição, procurar no changelog a CVE-2026-109618 e a CVE-2026-109619.
- Atualizar para o 8.5.12, 8.4.27, 8.3.36 ou 8.2.35, ou para o backport confirmado.
- Reiniciar o PHP-FPM, o Apache e o LiteSpeed e controlar as horas de arranque dos processos.
- Contraprova com
php -r 'var_dump(ini_get("memory_hard_limit_percent"));';bool(false)significa, segundo o manual, uma versão afetada. - Preservar os registos e verificá-los quanto a anomalias.
Como comprovar de forma sólida a versão e o nível de patches descreve-o Verificar corretamente a versão do PHP e o nível de patches.
Como ajuda concretamente o PHP SOS?
No contrato de manutenção de segurança, assumimos com a sua equipa a manutenção básica do PHP:
- Inventário: todas as variantes do PHP, versões, pools e locais de configuração por servidor.
- Configuração: valores relevantes para a segurança definidos com
php_admin_value, pools separados por site. - Atualizações: aplicação, reinício, verificação e documentação a cada versão de segurança.
- Transmitir conhecimento: explicamos aos seus admins o que alterámos e porquê.
Perguntas frequentes
Porque é que php -v mostra uma versão diferente da do site?
A linha de comandos, o PHP-FPM e o módulo Apache são programas separados, com versão e php.ini próprios. O php -v mostra apenas a linha de comandos. Para o site conta a versão do binário que realmente trata os pedidos.
Que php.ini vale no meu servidor?
Para a linha de comandos mostra-o o php --ini. Para o PHP-FPM existe geralmente um php.ini próprio e ficheiros de pool adicionais. Desde o PHP 8.5, o php --ini=diff mostra que valores se desviam da predefinição.
Qual é a diferença entre php_value e php_admin_value?
Ambos definem configurações num pool FPM. Os valores definidos com php_admin_value não podem, segundo o manual, ser sobrepostos pela aplicação com ini_set(). Para definições relevantes para a segurança, o php_admin_value é por isso a escolha certa.
Basta uma atualização sem reinício?
Não. Os processos PHP em execução mantêm o código antigo na memória. Após uma atualização, o PHP-FPM, o Apache com mod_php ou o LiteSpeed têm de ser reiniciados, caso contrário a versão vulnerável continua a correr.