2026年5月20日
2026年5月20日
WordPressのuploadsディレクトリでPHP実行を禁止する方法
はじめに
wp-content/uploads/はWordPressが画像などのメディアを保存するディレクトリです。このディレクトリにPHPファイルが設置されて実行できる状態になっていると、攻撃者がWebシェル(バックドア)をアップロードして任意のコードを実行できます。
症状・原因
- マルウェアスキャンで
wp-content/uploads/内にPHPファイルが検出された - セキュリティプラグインが「uploadsディレクトリでPHPが実行可能です」と警告した
- 不審なファイルが
wp-content/uploads/2024/01/shell.phpのようなパスで発見された - ファイルアップロード機能の脆弱性を突いてWebシェルが設置された
解決手順
ステップ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シェルが設置された可能性" "$ADMIN_EMAIL"
# 自動削除(慎重に使用)
# find "$UPLOADS_DIR" -name "*.php" -delete
fi
EOF
chmod +x /usr/local/bin/check-uploads-php.sh
# 1時間ごとに確認
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の場合、
location ~ \.php$の前にuploadsのブロックルールを記述しないと後者が優先されて実行できてしまう場合があります。ブロックルールは必ず上位に配置してください - 一部のプラグイン(例:Slider Revolution等)はuploads内に
.phpファイルを設置する場合があります。削除前に用途を確認し、不要なプラグインを削除した上で対応してください
まとめ
uploadsディレクトリのPHP実行禁止は①find wp-content/uploads -name ".php"で既存の不審ファイルを検出・削除、②Apacheはuploads/.htaccessにを追記、③Nginxはlocation ~ /wp-content/uploads/.*\.php$でdeny all、④wp_handle_upload_prefilterフックでPHPアップロード自体を拒否、⑤1時間ごとのcronでuploads内PHPファイルを監視します。