2026年11月12日

2026年11月12日

禁止 WordPress uploads 目录执行 PHP 的方法(.htaccess / Nginx)

本文是日语原文的本地化版本。 阅读日语原文

前言

wp-content/uploads/ 是 WordPress 保存图片等媒体文件的目录。如果这个目录中被放置了 PHP 文件,并且处于可以执行的状态,攻击者就可以上传 Web shell(后门),执行任意代码。

症状与原因

  • 恶意软件扫描在 wp-content/uploads/ 内检测到了 PHP 文件
  • 安全插件发出警告:“uploads 目录中可以执行 PHP”
  • 发现了路径类似 wp-content/uploads/2024/01/shell.php 的可疑文件
  • 攻击者利用文件上传功能的漏洞,植入了 Web shell

解决步骤

步骤1:检测已有的可疑 PHP 文件

# 搜索 uploads 目录内的全部 PHP 文件
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

# 查看最近(7 天内)创建或更新的 PHP 文件
find /var/www/html/wp-content/uploads -name "*.php" -mtime -7

# 检查文件内容(恶意软件的典型特征)
grep -rl "eval(base64_decode" /var/www/html/wp-content/uploads/
grep -rl "system\|exec\|passthru\|shell_exec" /var/www/html/wp-content/uploads/

# 删除可疑的 PHP 文件
find /var/www/html/wp-content/uploads -name "*.php" -delete
find /var/www/html/wp-content/uploads -name "*.phtml" -delete

步骤2:在 Apache 中禁止执行 PHP(.htaccess)

# 创建 wp-content/uploads/.htaccess
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
# 彻底禁止执行 PHP 文件
<FilesMatch "\.(php|phtml|php3|php4|php5|php7|phar|shtml)$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

# 直接禁用 PHP 引擎(使用 mod_php 时)
<IfModule mod_php.c>
    php_flag engine off
</IfModule>

# 同时禁止执行 CGI
Options -ExecCGI
RemoveHandler .php .phtml .php5 .phar

# 同时禁用目录列表
Options -Indexes
EOF

chmod 644 /var/www/html/wp-content/uploads/.htaccess
# 设置后的确认
# 创建测试用的 PHP 文件并尝试访问
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
# 返回 403 即为成功
rm /var/www/html/wp-content/uploads/test_block.php

步骤3:在 Nginx 中禁止执行 PHP

# /etc/nginx/sites-available/example.com
server {
    # ... 现有的配置 ...

    # 禁止在 uploads 目录中执行 PHP
    location ~* /wp-content/uploads/.*\.(php|phtml|php5|phar)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # 必须写在 PHP-FPM 的 location 之前
    location ~ \.php$ {
        # 常规的 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;
    }
}
# 检查 Nginx 配置并使其生效
sudo nginx -t && sudo systemctl reload nginx

# 确认
curl -o /dev/null -s -w "%{http_code}" https://example.com/wp-content/uploads/shell.php
# 返回 403 即为成功

步骤4:同时在 WordPress 中拦截 PHP 上传

// functions.php:禁止上传 PHP 文件本身

// ① 把 PHP 扩展名加入禁止上传的列表
add_filter('upload_mimes', function(array $mimes): array {
    // 移除与 PHP 相关的 MIME 类型(以防万一)
    unset($mimes['php'], $mimes['phtml'], $mimes['phar']);
    return $mimes;
});

// ② 检测并拒绝上传文件中的 PHP
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'] = '禁止上传 PHP 文件。';
    }

    // 也通过 MIME 类型确认
    if (str_contains($file['type'], 'php')) {
        $file['error'] = '禁止上传 PHP 文件。';
    }

    return $file;
});

步骤5:设置定期监控

# 定期监控 uploads 内 PHP 文件的脚本
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 "警告:在 uploads 目录中检测到 PHP 文件:
$PHP_FILES" | mail -s "[紧急] WordPress 上可能被植入了 Web shell" "$ADMIN_EMAIL"

    # 自动删除(请谨慎使用)
    # find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh

# 每小时检查一次
echo "0 * * * * root /usr/local/bin/check-uploads-php.sh" > /etc/cron.d/wp-uploads-php-check

注意事项

  • 通过 .htaccess 设置的 php_flag engine off 仅在使用 mod_php 时有效。如果使用的是 php-fpm(FastCGI),请用 指令或 Nginx 的 location 块来处理
  • 在 Nginx 中,如果不把 uploads 的拦截规则写在 location ~ \.php$ 之前,后者可能会优先生效,导致仍然可以执行。请务必把拦截规则放在更靠前的位置
  • 部分插件(例如 Slider Revolution 等)可能会在 uploads 内放置 .php 文件。删除之前请先确认其用途,并在删除不需要的插件之后再进行处理

总结

禁止 uploads 目录执行 PHP,按以下步骤进行:①用 find wp-content/uploads -name ".php" 检测并删除已有的可疑文件;②Apache 在 uploads/.htaccess 中追加 Deny from all;③Nginx 用 location ~ /wp-content/uploads/.*\.php$ 配置 deny all;④通过 wp_handle_upload_prefilter 钩子拒绝 PHP 文件本身的上传;⑤用每小时一次的 cron 监控 uploads 内的 PHP 文件。

关于 WordPress 有疑问?本站运营方位于日本,仅以日语回复。 联系我们(日语)

お気軽にご相談ください

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