Em resumo: php_admin_value e php_admin_flag definem configurações do PHP no pool PHP-FPM ou na configuração do Apache de modo que as aplicações não as possam alterar nem com ini_set() nem com .htaccess. O php.net exige precisamente isso para as medidas transitórias do PHP2Shell, por exemplo para memory_limit=-1. Depois de definir, o serviço tem de ser reiniciado e o valor deve ser verificado no contexto web.
Por que «definido» não significa «bloqueado»
Nos dias após 21 de outubro de 2026, muitos administradores escreveram as medidas transitórias do php.net no seu php.ini. Um pormenor da recomendação passou muitas vezes despercebido: memory_limit=-1 deve ser definido de modo que as aplicações não o possam sobrescrever. O php.net indica para isso expressamente php_admin_value no pool FPM ou na configuração do Apache.
A razão é simples. Muitos CMS, lojas e frameworks definem os seus próprios valores, por exemplo um limite de memória mais alto para importações. Se o valor estiver apenas no php.ini, a aplicação sobrescreve-o na chamada seguinte. A medida de proteção existe então no papel, mas não no processo em execução.
Isto não afeta apenas o PHP2Shell. Qualquer reforço, desde saídas de erro desativadas a limites de upload, é tão forte quanto o seu nível mais fraco.
Quem pode alterar as definições do PHP
O PHP conhece quatro modos de alteração. Cada definição tem um deles, que determina em que locais pode ser definida. Os significados provêm do manual do PHP.
| Modo | Onde o valor pode ser definido | Exemplos |
|---|---|---|
INI_USER |
no script com ini_set() e em .user.ini |
poucos valores de tempo de execução |
INI_PERDIR |
php.ini, .htaccess, httpd.conf, .user.ini |
post_max_size, session.upload_progress.enabled |
INI_SYSTEM |
apenas php.ini ou httpd.conf |
file_uploads, disable_functions |
INI_ALL |
em qualquer lado, também com ini_set() |
memory_limit, display_errors, open_basedir |
Os valores INI_ALL são os mais perigosos: podem ser alterados a partir de qualquer script. Os valores INI_PERDIR não podem ser alterados com ini_set(), mas sim através de um .htaccess com mod_php ou de um .user.ini com PHP-FPM. Quem tem direitos de escrita na raiz web, ou seja, também o código introduzido, pode criar esses ficheiros.
php_admin_value no pool FPM e no Apache
No PHP-FPM, os valores estão no ficheiro do pool. O manual do PHP estabelece: os valores definidos com php_admin_value e php_admin_flag não podem ser sobrescritos com ini_set(). Para valores de ligar e desligar use php_admin_flag, para todos os outros php_admin_value.
; /etc/php/8.3/fpm/pool.d/seite1.conf (excerto)
[seite1]
user = seite1
group = seite1
listen = /run/php/seite1.sock
php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
php_admin_flag[session.upload_progress.enabled] = off
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/php/seite1-fehler.log
php_admin_value[open_basedir] = /var/www/seite1/:/tmp/seite1/
Segundo o php.net, o memory_limit=-1 só pertence à configuração juntamente com um limite de memória através de contentor ou cgroup. Como isso se consegue com o systemd está no artigo Definir limites de memória com systemd e cgroups.
No Apache com mod_php, as diretivas pertencem à configuração do servidor ou ao VirtualHost. Segundo o manual do PHP, não são permitidas em .htaccess e, uma vez definidas, nem o .htaccess nem o ini_set() as podem alterar.
<VirtualHost *:443>
ServerName www.example.de
DocumentRoot /var/www/seite1/public
<IfModule php_module>
php_admin_value memory_limit -1
php_admin_value post_max_size 32M
php_admin_value upload_max_filesize 24M
php_admin_flag session.upload_progress.enabled off
php_admin_flag display_errors off
</IfModule>
</VirtualHost>
Duas subtilezas do manual: para apagar um valor definido anteriormente, use none como valor. E as constantes do PHP como E_ALL não têm significado na configuração do Apache; para error_reporting, tem de indicar aí o valor numérico.
Que valores deve bloquear
Nem todas as definições têm de estar bloqueadas. Faz sentido para tudo o que diz respeito à segurança ou serve como medida transitória:
- Os valores transitórios do PHP2Shell do php.net:
memory_limit,post_max_size,upload_max_filesize,session.upload_progress.enablede, no PHP 8.5,fatal_error_backtraces. - Saída de erros e registo:
display_errors,display_startup_errors,log_errors,error_log. - Acesso a ficheiros e isolamento:
open_basedir,upload_tmp_dir,session.save_path. - Acessos de rede a partir do PHP:
allow_url_includee, se a aplicação não precisar,allow_url_fopen. - Funções bloqueadas através de
disable_functions, que no pool, segundo o manual, complementam a lista do php.ini e não a substituem. Pormenores no guia Usar corretamente o disable_functions.
No caso do session.upload_progress.enabled, o bloqueio é particularmente importante, porque o valor poderia, caso contrário, ser reativado através de um .user.ini. Mais informação em Desativar o session.upload_progress: de forma correta e duradoura.
Verificar se o bloqueio funciona
Após cada alteração, reinicie o serviço e verifique o valor no contexto web. Um ficheiro de teste breve, eliminado logo a seguir, mostra se o pool mantém o valor mesmo quando a aplicação o quer alterar:
<?php
// Ficheiro de teste: colocar por pouco tempo, abrir uma vez através do domínio, apagar de imediato
header('Content-Type: text/plain');
$vorher = ini_get('memory_limit');
$versuch = @ini_set('memory_limit', '256M');
echo "memory_limit: $vorher\n";
echo 'Änderung per ini_set() ', ($versuch === false ? 'blockiert' : 'MÖGLICH'), "\n";
Espera-se -1 e «blockiert». Se a saída for «MÖGLICH», o valor não está definido através de php_admin_value ou o serviço ainda não foi reiniciado. Repita a verificação para cada pool e cada versão do PHP.
Mantenha os valores bloqueados registados de forma centralizada, por exemplo num modelo de pool ou na sua gestão de configuração. Os painéis de alojamento sobrescrevem por vezes, na gravação seguinte, ficheiros de pool alterados à mão; aí os valores pertencem aos campos previstos pelo painel.
Como o PHP ordena, no seu conjunto, os níveis de configuração é explicado em O php.ini explicado: estrutura, níveis e precedência. As medidas transitórias completas estão em Medidas imediatas, quando ainda não pode aplicar o patch.
Conclusão: só bloqueado está realmente definido
As medidas transitórias do php.net para o PHP2Shell trouxeram à consciência uma distinção que antes passava muitas vezes despercebida: para muitas definições, um valor no php.ini é apenas uma sugestão, um valor em php_admin_value é uma imposição. Para valores de conforto, como o fuso horário, a diferença é irrelevante. Para definições de segurança e medidas transitórias, decide se a medida chega sequer a atuar na operação.
O esforço é reduzido: um punhado de linhas por pool ou VirtualHost, um reinício, uma breve verificação. Mantenha a lista dos valores bloqueados curta e fundamentada, para que os programadores possam perceber por que razão a sua aplicação não pode alterar um valor. E mantenha a lista nos seus modelos, para que os novos sites a herdem automaticamente.
Como ajuda concretamente a PHP SOS?
- Ler os níveis: determinamos, para cada site, que valores do php.ini, do pool, do Apache, do
.htaccessou do.user.inise aplicam efetivamente. - Definir bloqueios: registamos os valores relevantes para a segurança e as medidas transitórias do PHP2Shell como
php_admin_valueouphp_admin_flage reiniciamos os serviços. - Testar a aplicação: verificamos se a aplicação corre sem erros com os valores bloqueados e analisamos o registo de erros.
- Manter modelos: no âmbito do reforço de segurança de servidores, incorporamos os valores em modelos de pool e na documentação.
Perguntas frequentes
Qual é a diferença entre php_value e php_admin_value?
Ambos definem uma configuração do PHP. Os valores de php_value podem ser alterados mais tarde pela aplicação, por exemplo com ini_set() ou .htaccess. Segundo o manual do PHP, os valores de php_admin_value e php_admin_flag estão bloqueados para o ini_set() e, no Apache, também para o .htaccess.
Posso escrever php_admin_value num ficheiro .htaccess?
Não. Segundo o manual do PHP, o php_admin_value não é permitido em ficheiros .htaccess. Pertence à configuração do servidor Apache ou ao VirtualHost e, no PHP-FPM, ao ficheiro do pool.
O que acontece se uma aplicação quiser alterar um valor bloqueado?
A chamada ao ini_set() falha e devolve false; o valor bloqueado mantém-se. As aplicações bem programadas lidam com isso. Ainda assim, após a alteração, verifique o registo de erros e as funções mais importantes.
Tenho de reiniciar após uma alteração no pool?
Sim. O PHP-FPM lê os ficheiros do pool no arranque ou ao recarregar o serviço. No Apache com mod_php, o mesmo se aplica à configuração do servidor. Sem reinício, o valor antigo continua a correr.
É possível alargar o disable_functions no pool?
Sim, com uma particularidade: segundo o manual do PHP, o disable_functions no pool FPM não sobrescreve os valores do php.ini, mas complementa-os. O pool pode, portanto, bloquear mais funções, mas não libertar nenhuma.