WP-CLIとSQLでワードプレスの隠蔽バックドアを見つける方法
2026年7月30日
0
Internet TechnologyRelated Video
5:04これはWordPress史上最悪のハックなのか?
Better Stack
Comments (0)
Log in to leave a comment
No posts yet
5:04Better Stack
Log in to leave a comment
No posts yet
外注で制作したWordPressサイトのコアアップデートボタンを押すのは、なかなか躊躇してしまうものです。テーマやカスタムプラグ인の互換性が崩れて画面が真っ白になるのが怖くて後回しにしていると、いつの間にかサイトは脆弱性だらけになってしまいます。すでに侵入されているかもしれないという不安に襲われたときに、最も素早くデータベースとサーバーをチェックする実務点検の手順です。
攻撃者は通常、目立たないように侵入してきます。データベースの wp_usermeta テーブルを直接操作し、既存のアカウントにこっそり管理者権限を付与するといった手法です。通常のログイン一覧には見えにくいですが、DBを直接照会すればすぐに判明します。
sql SELECT u.ID, u.user_login, u.user_email, u.user_registered, m.meta_value AS capabilities FROM wp_users u INNER JOIN wp_usermeta m ON u.ID = m.user_id WHERE m.meta_key = 'wp_capabilities' AND ( m.meta_value LIKE '%"administrator"%' OR m.meta_value LIKE '%"administrator":true%' ) ORDER BY u.user_registered DESC;
次はファイルシステムです。画像やドキュメントのみが存在するはずの wp-content/uploads ディレクトリにPHPファイルが紛れ込んでいる場合、十中八九バックドアです。SSHターミナルを開き、危険なファイルが存在しないかチェックします。
`bash
find wp-content/uploads/ -type f -name "*.php" -ls
find . -type f -name "*.php" -exec grep -HnE "(eval(|base64_decode(|gzinflate(|passthru(|shell_exec()" {} ;
wp core verify-checksums --include-root
`
ログの確認も必須です。REST APIを狙った攻撃は通常、短時間にPOSTリクエストを大量に送信し、200 や 201 レスポンスを受け取ります。Nginxの access.log から不審な挙動を示したリクエストを抽出します。
bash grep -E "POST|PUT" /var/log/nginx/access.log | grep -E "/wp-json/|rest_route=" | awk '$9 ~ /^(200|201|207)$/ {print $1, $4, $6, $7, $9}' | sort | uniq -c | sort -nr | head -n 30
本番稼働中のサイトに直接パッチを適用するのは、度胸というより無謀に近い行為です。データベースとファイルシステムを丸ごと複製したステージング環境を事前に作成します。
`bash
wp db export production_backup.sql --add-drop-table
rsync -avz --exclude='wp-content/cache' /var/www/html/ staging:/var/www/staging/
wp db import production_backup.sql
wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid
wp plugin list --update=available --fields=name,version,update_version,requires_php --format=table
`
複製が完了したらアップデートを実行し、5分間だけでも主要機能を実際に操作してみます。会員登録、ログイン、カート追加、決済画面の呼び出し、お問い合わせフォームの送信まで、直接確認してこそ安心できます。
プラグインの開発元がアップデートを提供してくれず、コアをすぐに更新できないもどかしい状況もあります。そのような場合は、サーバーレベルやWAFで特定パスへのアクセスを遮断することで時間を稼ぎます。Nginxを使用している場合は、nginx.conf で自身のIPアドレス以外からのREST APIユーザー作成およびバッチ処理エンドポイントへのアクセスを拒否します。
nginx location ~* ^/wp-json/(batch/v1|wp/v2/users) { limit_except GET { allow 192.0.2.1; deny all; } try_files $uri $uri/ /index.php?$args; }
万が一の事態に備えて、DBとアップロードフォルダをS3に転送するバックアップスクリプトも併せて設定しておきます。
`bash
#!/bin/bash
WP_PATH="/var/www/html"
BACKUP_DIR="/tmp/wp_backups"
DATE=$(date +%Y%m%d_%H%M%S)
S3_BUCKET="s3://my-wordpress-secure-backups"
mkdir -p $BACKUP_DIR
wp db export BACKUP_DIR/db_DATE.sql --path=$WP_PATH --quiet
tar -czf BACKUP_DIR/files_DATE.tar.gz -C $WP_PATH wp-content/uploads/
aws s3 cp BACKUP_DIR/db_DATE.sql S3_BUCKET/db_DATE.sql
aws s3 cp BACKUP_DIR/files_DATE.tar.gz S3_BUCKET/files_DATE.tar.gz
find $BACKUP_DIR -type f -mtime +7 -delete
`
悪意のあるコードを削除し、セキュリティパッチを適用したからといって終わりではありません。攻撃者が盗み出したセッションクッキーを使って再侵入する可能性があるからです。既存のセッションを破棄し、wp-config.php のソルトキーをすべて再生成します。
`bash
wp user list --field=ID | xargs -n 1 wp user session destroy --all
wp config shuffle-salts
`
管理画面内からプラグインやテーマファイルを直接編集する機能も無効化します。万が一攻撃者に権限を乗っ取られても、コードの注入を防ぐ最小限の安全装置となります。wp-config.php に以下の2行を追加します。
php define( 'DISALLOW_FILE_EDIT', true ); define( 'DISALLOW_FILE_MODS', true );
最後に、未ログインのユーザーがREST API経由でユーザー一覧を閲覧できないよう、mu-plugins ディレクトリに専用のフィルターを設置します。
`php
<?php
/**