2026年11月12日

2026年11月12日

Como bloquear a execução de PHP na pasta uploads do WordPress

Este artigo é uma edição localizada do original em japonês. Ler o original em japonês

Introdução

A pasta wp-content/uploads/ é onde o WordPress guarda imagens e outras mídias. Se arquivos PHP forem colocados nessa pasta e puderem ser executados, um invasor pode enviar um web shell (backdoor) e executar código arbitrário.

Sintomas e causas

  • Uma varredura de malware detectou arquivos PHP dentro de wp-content/uploads/
  • Um plugin de segurança avisou que "o PHP pode ser executado na pasta uploads"
  • Um arquivo suspeito foi encontrado em um caminho como wp-content/uploads/2024/01/shell.php
  • Um web shell foi instalado explorando uma vulnerabilidade na função de envio de arquivos

Passo a passo da solução

Passo 1: detecte os arquivos PHP suspeitos já existentes

# Procura todos os arquivos PHP dentro da pasta uploads
find /var/www/html/wp-content/uploads -name "*.php" -type f
find /var/www/html/wp-content/uploads -name "*.phtml" -type f
find /var/www/html/wp-content/uploads -name "*.php5" -type f

# Verifica os arquivos PHP criados ou alterados recentemente (nos últimos 7 dias)
find /var/www/html/wp-content/uploads -name "*.php" -mtime -7

# Verifica o conteúdo dos arquivos (padrões típicos de malware)
grep -rl "eval(base64_decode" /var/www/html/wp-content/uploads/
grep -rl "system\|exec\|passthru\|shell_exec" /var/www/html/wp-content/uploads/

# Apaga os arquivos PHP suspeitos
find /var/www/html/wp-content/uploads -name "*.php" -delete
find /var/www/html/wp-content/uploads -name "*.phtml" -delete

Passo 2: bloqueie a execução de PHP no Apache (.htaccess)

# Cria o wp-content/uploads/.htaccess
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
# Proíbe completamente a execução de arquivos PHP
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phar|shtml)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

# Desativa o próprio mecanismo PHP (ao usar mod_php)
<IfModule mod_php.c>
    php_flag engine off
</IfModule>

# Proíbe também a execução de CGI
Options -ExecCGI
RemoveHandler .php .phtml .php5 .phar

# Desativa também a listagem de diretórios
Options -Indexes
EOF

chmod 644 /var/www/html/wp-content/uploads/.htaccess
# Verificação após a configuração
# Cria um arquivo PHP de teste e tenta acessá-lo
echo "<?php echo 'test'; ?>" > /var/www/html/wp-content/uploads/test_block.php
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/test_block.php
# Se retornar 403, deu certo
rm /var/www/html/wp-content/uploads/test_block.php

Passo 3: bloqueie a execução de PHP no Nginx

# /etc/nginx/sites-available/example.com
server {
    # ... configuração existente ...

    # Proíbe a execução de PHP na pasta uploads
    location ~* /wp-content/uploads/.*\.(php|phtml|php5|phar)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Escreva antes do location do PHP-FPM
    location ~ \.php$ {
        # Processamento normal de PHP
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
# Verifica a configuração do Nginx e a aplica
sudo nginx -t && sudo systemctl reload nginx

# Verificação
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/shell.php
# Se retornar 403, deu certo

Passo 4: bloqueie também o envio de PHP pelo próprio WordPress

// functions.php: proíbe o próprio envio de arquivos PHP

// ① Adiciona as extensões PHP à lista de envio proibido
add_filter('upload_mimes', function(array $mimes): array {
    // Remove os tipos MIME relacionados a PHP (por precaução)
    unset($mimes['php'], $mimes['phtml'], $mimes['phar']);
    return $mimes;
});

// ② Detecta e recusa arquivos PHP enviados
add_filter('wp_handle_upload_prefilter', function(array $file): array {
    $dangerous_extensions = ['php', 'phtml', 'php3', 'php4', 'php5', 'phar', 'shtml'];
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

    if (in_array($ext, $dangerous_extensions, true)) {
        $file['error'] = 'O envio de arquivos PHP é proibido.';
    }

    // Verifica também pelo tipo MIME
    if (str_contains($file['type'], 'php')) {
        $file['error'] = 'O envio de arquivos PHP é proibido.';
    }

    return $file;
});

Passo 5: configure um monitoramento periódico

# Script que monitora periodicamente os arquivos PHP dentro do uploads
cat > /usr/local/bin/check-uploads-php.sh << 'EOF'
#!/bin/bash
UPLOADS_DIR="/var/www/html/wp-content/uploads"
ADMIN_EMAIL="admin@example.com"

PHP_FILES=$(find "$UPLOADS_DIR" -name "*.php" -o -name "*.phtml" -o -name "*.phar" 2>/dev/null)

if [ -n "$PHP_FILES" ]; then
    echo "Aviso: foram detectados arquivos PHP na pasta uploads:
$PHP_FILES" | mail -s "[URGENTE] Possível web shell instalado no WordPress" "$ADMIN_EMAIL"

    # Remoção automática (use com cuidado)
    # find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh

# Verifica a cada hora
echo "0 * * * * root /usr/local/bin/check-uploads-php.sh" > /etc/cron.d/wp-uploads-php-check

Observações

  • O php_flag engine off do .htaccess só funciona com o mod_php. Se você usa php-fpm (FastCGI), use a diretiva ou o bloco location do Nginx
  • No Nginx, se a regra de bloqueio do uploads não for escrita antes de location ~ \.php$, esta última pode ter prioridade e o arquivo acabar sendo executado. Coloque sempre a regra de bloqueio mais acima
  • Alguns plugins (por exemplo, o Slider Revolution) podem colocar arquivos .php dentro do uploads. Antes de apagar, verifique para que servem e, depois de remover os plugins desnecessários, aplique a correção

Resumo

Para bloquear a execução de PHP na pasta uploads: ① detecte e apague os arquivos suspeitos existentes com find wp-content/uploads -name ".php"; ② no Apache, acrescente Deny from all ao uploads/.htaccess; ③ no Nginx, use deny all em location ~ /wp-content/uploads/.*\.php$; ④ recuse o próprio envio de PHP com o hook wp_handle_upload_prefilter; ⑤ monitore os arquivos PHP dentro do uploads com um cron a cada hora.

Dúvidas sobre WordPress? Quem publica este site fica no Japão e responde em japonês. Contato (em japonês)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲