Em resumo: Para proibir a execução de PHP em uploads, determine primeiro todas as pastas em que o PHP pode escrever e bloqueie depois, em cada uma delas, a execução de scripts na configuração do servidor, não por .htaccess. No Nginx, o bloqueio tem de atuar antes do bloco PHP geral; no Apache, pertence ao VirtualHost com AllowOverride None. security.limit_extensions = .php no pool FPM e um teste com um ficheiro inofensivo concluem o trabalho.
Por que razão as pastas de uploads contam precisamente agora
Após uma vulnerabilidade crítica como o PHP2Shell, os atacantes raramente querem executar código apenas uma vez. Querem regressar, mesmo que o servidor seja corrigido mais tarde. O caminho mais simples para isso é uma webshell: um pequeno ficheiro PHP, colocado numa pasta com permissão de escrita e chamado mais tarde através do navegador.
Um patch não remove um ficheiro destes. Quem esteve online sem patch a partir de 20 de outubro de 2026 deve, por isso, não só atualizar, mas também verificar se há novos ficheiros PHP em algum lado e impedir daqui em diante que sejam executados. Como interpretar as ocorrências é descrito em Ficheiros PHP na pasta de uploads: interpretar corretamente as ocorrências.
O bloqueio de execução atua sobre a segunda condição. Não impede que um ficheiro seja colocado, mas que o servidor o trate como programa.
Primeiro o inventário: onde pode o PHP escrever?
A maioria dos guias refere apenas a pasta de uploads. Na prática, uma aplicação PHP escreve em muito mais sítios. Cada um deles que seja acessível através do servidor web precisa do bloqueio.
| Tipo de pasta | Conteúdo típico | Por que tem escrita |
|---|---|---|
| Uploads, multimédia | imagens, PDF, anexos | utilizadores e redação carregam ficheiros |
| Cache | páginas geradas, miniaturas | a aplicação acelera a entrega |
| Temporários, importação, exportação | ficheiros CSV, estados intermédios | interfaces e troca de dados |
| Cópias de segurança na raiz web | .zip, .sql |
extensões guardam «no local» |
| Registos na raiz web | registos de erros e de depuração | aplicações mal configuradas |
As pastas que isto significa no seu servidor são mostradas por uma pesquisa com os direitos do utilizador de execução. Não altera nada:
# Todas as pastas sob /var/www em que o utilizador do PHP pode escrever
# (adaptar o utilizador: www-data, nginx, apache ou utilizador próprio do pool)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Já existem ficheiros PHP nestas pastas?
sudo -u www-data find /var/www -type d -writable -print0 2>/dev/null \
| xargs -0 -I{} find {} -maxdepth 1 -type f -iname "*.ph*" 2>/dev/null
Se a primeira pesquisa devolver toda a raiz web, o código do programa pertence ao utilizador de execução. Deve alterá-lo antes, como descreve o guia Permissões de ficheiros no servidor web. Caso contrário, não há nenhuma pasta que não precise de ser bloqueada.
Proibir a execução de PHP em uploads: Nginx
No Nginx, a ordem decide. Segundo a documentação do Nginx, as expressões regulares são verificadas pela ordem do ficheiro de configuração, e ganha a primeira correspondência. Se o bloco geral location ~ \.php$ estiver antes do seu bloqueio, o ficheiro é executado. Uma location de prefixo simples, sem ^~, não protege pela mesma razão.
Seguro é uma expressão regular para todas as pastas bloqueadas, colocada antes do bloco PHP. Cobre também extensões raramente usadas:
server {
# ... configuração de base ...
# 1. Bloqueio para pastas com escrita, TEM de estar antes do bloco PHP
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Bloco PHP geral: passar apenas ficheiros existentes
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/seite1.sock;
}
}
Adapte os nomes das pastas ao seu inventário. Em aplicações com um único ponto de entrada, o caminho por uma lista de permissões é ainda mais forte; o modelo está em Configurar o Nginx para PHP com segurança.
Apache e PHP-FPM: o bloqueio no sítio certo
No Apache, o bloqueio pertence à configuração do servidor ou ao VirtualHost. Um .htaccess na pasta de uploads é inadequado, porque qualquer pessoa com escrita nessa pasta o pode alterar. Para toda a raiz web aplica-se, por isso, AllowOverride None. Segundo a documentação do Apache, o AllowOverride só é permitido em blocos <Directory> sem expressões regulares; defina-o, portanto, na raiz web e o bloqueio por <DirectoryMatch> por baixo:
<Directory /var/www/seite1/public>
AllowOverride None
Require all granted
</Directory>
<DirectoryMatch "^/var/www/seite1/public/(uploads|media|cache|tmp|export)/">
<FilesMatch "\.(php\d?|phtml|phar|pht|phps)$">
Require all denied
</FilesMatch>
</DirectoryMatch>
Se ainda correr o mod_php, acrescente no mesmo bloco php_admin_flag engine off. No PHP-FPM, atua uma segunda barreira no pool: o security.limit_extensions determina que extensões o FPM executa. Segundo o manual do PHP, o valor por defeito é .php .phar; recomenda-se a restrição a .php.
; no pool, p. ex. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Testar com um ficheiro inofensivo
Se o bloqueio funciona, só um teste o mostra. Coloque por breves instantes em cada pasta bloqueada um ficheiro que apenas apresente um texto, chame-o através do domínio e elimine-o depois.
- Verificar a configuração:
nginx -touapachectl configtest, depois recarregar. - Criar o ficheiro de teste, por exemplo
uploads/sperrtest.phpcom o conteúdo<?php echo 'ausgefuehrt';. - Chamar com
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Espera-se403. - Se, em vez disso, aparecer
200e o texto «ausgefuehrt», o bloqueio não atua. Verificar configuração e ordem. - Eliminar o ficheiro de teste e repetir o teste para cada pasta e cada site.
Se, no inventário, encontrar já ficheiros PHP desconhecidos em pastas com escrita, não elimine nada precipitadamente. Preserve primeiro o estado e os registos, pois esses ficheiros são meios de prova. Como proceder depois é descrito em Reconhecer e remover webshells.
Como se constroem com segurança as funções de upload no código, com verificação de tipo e armazenamento fora da raiz web, está no guia Implementar uploads de ficheiros em PHP com segurança.
Conclusão: escrever sim, executar não
O bloqueio de execução em pastas com escrita é uma das medidas isoladas mais eficazes contra portas dos fundos permanentes. Custa poucas linhas de configuração e não estraga nada em aplicações bem construídas. Três coisas são decisivas: um inventário completo, em vez de apenas a pasta de uploads óbvia, a ordem correta no Nginx ou o nível correto no Apache e um teste real com um ficheiro inofensivo.
Complementado por proprietários separados para o código do programa, security.limit_extensions no pool e uma pesquisa regular de novos ficheiros PHP, chega-se a um estado em que um ficheiro colocado é irritante, mas dificilmente utilizável. Isto não substitui a atualização nem a pesquisa de vestígios, mas retira aos atacantes uma das suas ferramentas mais importantes.
Como ajuda concretamente a PHP SOS?
- Inventário: determinamos todas as pastas com escrita por site e verificamos se já contêm ficheiros PHP.
- Definir bloqueios: registamos os bloqueios de execução no Nginx, no Apache e no PHP-FPM, na ordem certa e sem dependência do
.htaccess. - Testar: verificamos cada bloqueio com um ficheiro inofensivo e documentamos o resultado.
- Limpar: perante ocorrências, assumimos a preservação de vestígios e a remoção de malware.
Perguntas frequentes
Basta um .htaccess na pasta de uploads para proibir o PHP?
Não de forma fiável. Quem pode escrever na pasta pode também alterar ou substituir o .htaccess. O bloqueio pertence à configuração do servidor ou ao VirtualHost e, para a raiz web, deve aplicar-se AllowOverride None.
Que pastas tenho de bloquear?
Todas as pastas em que o utilizador do PHP pode escrever e que são acessíveis através do servidor web. Além das pastas de uploads, são muitas vezes diretórios de cache, temporários, de importação, de exportação e de cópias de segurança. Determine-as com uma pesquisa feita como utilizador de execução.
O bloqueio estraga o meu site?
Em regra, não, pois nas pastas de uploads e de cache de aplicações bem construídas não há scripts chamados diretamente. Algumas extensões colocam, no entanto, ficheiros PHP aí. Por isso, teste as funções mais importantes depois da alteração.
O bloqueio protege contra o PHP2Shell?
Não. O PHP2Shell é uma vulnerabilidade no interpretador PHP, que só se fecha com a atualização e o reinício de todos os workers. O bloqueio impede, no entanto, que um ficheiro colocado seja mais tarde chamado através do navegador e usado como porta dos fundos permanente.