Situação atual: PHP2Shell. Duas vulnerabilidades críticas do PHP (CVSS 9,2) permitem executar código malicioso sem autenticação. Patches disponíveis desde 21/10/2026.O que fazer agora →

Proibir a execução de PHP em pastas de uploads

Uma webshell precisa de duas coisas: uma pasta onde possa ser escrita e um servidor que a execute. Como retirar-lhe a segunda, e em todas as pastas com escrita, não apenas em uploads.

Atualizado em 6 min de leituraHardening e configuração

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.

  1. Verificar a configuração: nginx -t ou apachectl configtest, depois recarregar.
  2. Criar o ficheiro de teste, por exemplo uploads/sperrtest.php com o conteúdo <?php echo 'ausgefuehrt';.
  3. Chamar com curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Espera-se 403.
  4. Se, em vez disso, aparecer 200 e o texto «ausgefuehrt», o bloqueio não atua. Verificar configuração e ordem.
  5. Eliminar o ficheiro de teste e repetir o teste para cada pasta e cada site.
Importante

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.

Fontes

Contacto imediato

Cada hora conta. Escreva-nos agora.

Descreva brevemente o sistema, a versão do PHP e o que observou. Entramos em contacto consigo, esclarecemos a situação e trabalhamos remotamente até o incidente estar concluído e documentado.

Ajuda imediata