「怪しいファイルは自分で削除した」「セキュリティスキャンも異常なしだった」——それだけで、本当に駆除できたと言い切れますか?
画面が元に戻っても、マルウェアが別の場所に残り、検索エンジンにだけ不正ページを見せ続けていることがあります。
今回のご相談者も、自分で不正ファイルを削除し「駆除できた」と考えていました。
ところが、わたしが専門調査を行うと、独自テーマ内に検索エンジン向けの不正コードが残っていました。
一般の訪問者には正常なサイトを表示するため、本人もセキュリティプラグインも異常に気づけない状態です。
この記事では、自己駆除では終わらなかったSEOスパムを発見し、残存コードを駆除してGoogleの正常確認まで行った流れを匿名で解説します。
WordPressの復旧を多数手がけてきたよこやま良平です。今回も、サイト所有者が駆除済みと考えていた環境を再調査し、通常閲覧では見えない残存マルウェアを発見・駆除しました。
- 自分で駆除したのにマルウェアが残っていた経緯
- Googlebotだけに不正HTMLを返すクローキングの仕組み
- 専門調査で残存コードを発見・駆除した流れ
- 不審なコードを1か所消すだけでは危険な理由
- 専門家へ切り替えるべき判断基準
結論から言うと、「怪しい部分を消した」「画面が直った」「スキャンが正常だった」は、完全駆除の証明になりません。
自分だけの確認で終わらせず、表示条件の比較、ファイル全体、データベース、ログまで専門的に調べる必要があります。
WordPressマルウェアを自分で駆除したはずなのに残っていた
今回の重要な点は、相談前にサイト所有者が不審なファイルを見つけ、自分で削除していたことです。
通常画面は元に戻り、セキュリティプラグインでも異常が見つからなかったため、駆除できたと考えていました。
「画面が直ったから大丈夫」と判断していた
自分で削除した直後にサイトが正常表示へ戻れば、「これで終わった」と思うのは自然です。
しかし、見つけたファイルが唯一の感染箇所とは限らず、攻撃者が残した別のコードが静かに動き続けることがあります。
今回も一般の訪問者には正常なページが表示されていました。
異常を示していたのは、Google Search Consoleが「XMLサイトマップではなくHTMLを受信した」と判定したことだけでした。

専門家がGooglebotの条件で再調査した
わたしはGoogle側の誤判定と決めつけず、通常ブラウザとGooglebotで同じサイトマップを取得して比較しました。
すると、通常ブラウザには正しいXMLが返る一方、Googlebot・Bingbotには約184KBの海外ギャンブル系HTMLが返りました。
さらに、存在しないURLでもBotにだけ同じ不正HTMLがHTTP 200で返されました。
この時点で、自己駆除後も検索エンジン向けマルウェアが残存していると判断できました。
- 通常ブラウザ:正しいXMLサイトマップ
- Googlebot・Bingbot:海外ギャンブル系HTML
- 存在しないURL:Botには不正HTMLを200で返す
- 既存の画像・CSSなど静的ファイル:正常
このように相手によって内容を変える手口を「クローキング」と呼びます。
所有者の確認時だけ正常に見せられるため、自分で直ったと思っても、検索エンジン側では被害が続いているのです。

WordPressのSEOスパムをセキュリティプラグインが見逃した理由
今回のSEOスパムが見つかりにくかった最大の理由は、典型的なウイルスらしい見た目ではなかったことです。
難読化された文字列や、分かりやすいWebシェルは使われていませんでした。
普通のPHP関数を組み合わせていた
感染コードは、User-Agentの確認、外部URLへの通信、HTMLの出力、処理終了という一般的なPHP機能を組み合わせていました。
それぞれの関数は正規プラグインやAPI連携でも使われるため、単語だけで危険と判定すると誤検知が増えます。
よくある eval(base64_decode(...)) 型の難読化ではなく、読みやすいコードとして追記されていました。
既知のマルウェア署名だけを探すスキャンでは、判定が難しい種類です。
独自テーマは公式チェックサムで比較できない
WordPress本体や公式プラグインは、配布元の正規ファイルとハッシュを比較できます。
一方、制作会社や運営者が作った独自テーマには、WordPress.orgが提供する正解のチェックサムがありません。
今回も、独自テーマの functions.php の末尾へ約150行のコードが追加されていました。
テーマ本来の機能がそのまま動くため、公開画面を見ただけでは改ざんに気づけません。
スキャン対象外の場所に入っていた
セキュリティ機能には、それぞれ検査できる範囲があります。
コアの公式照合とuploads内の危険ファイル確認を中心とする簡易検査では、テーマ内部の全PHPまでは調べません。
これはセキュリティプラグインが無意味という話ではありません。
不正ログイン防止、既知パターンの検出、改ざん通知などに有効ですが、1つの検査結果だけで完全な安全を証明することはできないという意味です。
ファイル検査と実際の通信結果は別の確認だった
ファイルスキャンは、保存されているコードを既知の署名や危険度の高い関数と照合する方法が中心です。
一方、今回の異常は「誰がアクセスしたか」によって初めて表面化するため、実際にGooglebotを名乗って通信しなければ再現できませんでした。
つまり、検査画面の結果だけを見る静的な確認と、外部からアクセスして返答を比べる動的な確認の両方が必要です。
さらに、通信先のドメインが変更されたり、不正HTMLを返す時間帯や国が限定されたりすると、一度の確認では正常に見えることもあります。
専門調査では、Googlebotだけでなく通常ブラウザ、Bingbot、スマートフォンなど複数条件で同じURLを取得し、ステータスコード、Content-Type、本文サイズ、本文ハッシュを比較します。
この差分が感染箇所を絞る重要な証拠になります。
- 独自テーマと独自プラグインの内容
- データベース内の不正な設定値や予約処理
- 検索エンジンと一般閲覧者への応答差
- 上位階層の設定ファイルやサーバー側キャッシュ
- 侵入経路、漏えいした認証情報、再生成元

WordPressのSEOスパムを作ったコードの仕組み
不正コードは、アクセスしてきた相手を判定し、条件に合う時だけ攻撃者側のHTMLを取得して返す仕組みでした。
サイト名、会社名、ドメイン、認証情報は伏せ、動作を理解するために必要な部分だけ紹介します。

検索エンジンBotだけを選別する
コードにはGooglebot、Bingbot、Googleの検査ツールなど、多数のBot名が並んでいました。
通常のブラウザにはWordPress本来の処理を続け、Botの場合だけ別の処理へ分岐します。
外部サーバーから不正HTMLを取得する
Botと判定すると、現在アクセスされているURLを攻撃者側へ送り、返されたHTMLを表示していました。
そのためサイト内に巨大なスパムHTMLが保存されていなくても、外部から毎回内容を取り寄せられます。
訪問者情報も外部へ送信する
さらに、IPアドレス、閲覧URL、User-Agent、参照元、使用言語を外部へ送る処理もありました。
国、端末、検索経由かどうかによって、不正表示の対象を細かく選別するためと考えられます。
専門家が残存マルウェアを発見して駆除した流れ
専門調査では、所有者がすでに削除した箇所だけを確認するのではなく、「まだ何か残っている」ことを前提にゼロから調べ直しました。
症状を再現し、証拠を保全してから、正常なものまで壊さずに感染範囲を狭めています。
- 自己駆除で削除したもの、発生した症状、作業日時を聞き取る
- 通常ブラウザとGooglebotでサイトマップの応答を比較する
- レスポンスヘッダー、本文サイズ、Content-Typeを証拠として記録する
- WordPress本体、テーマ、プラグイン、uploads、サーバー設定を解析する
- データベースの管理者、オプション、Cron、投稿データも確認する
- 公式チェックサムとコードの動作から残存箇所を特定する
- 原本を保全したうえで不正コードを駆除し、キャッシュを削除する
- 通常UA・Googlebot・Bingbotで再検証し、Search Consoleへ再送信する
WordPress本体と公式プラグインを照合した
WordPress本体は同じバージョンの公式配布物と照合し、公式プラグインもチェックサムを確認しました。
uploads内のPHP、画像に偽装したコード、.user.iniによる自動読み込みも調べました。
自己駆除で見落とされたコードを独自テーマから発見した
最終的に、独自テーマの functions.php で、正常な関数が終了した直後に不正ブロックが追記されていることを確認しました。
これはサイト所有者が自分で駆除した際には発見できず、そのまま残っていたコードです。
不正コードはGooglebotなどを判別し、攻撃者の外部サーバーからHTMLを取得していました。
同じ通信先や特徴的な文字列をサイト一式とデータベースで追跡し、ほかに残存がないか確認してから駆除しました。
復旧後はGooglebotでもXMLになった
残存コードの駆除とキャッシュ整理後、通常ブラウザ、Googlebot、Bingbotでサイトマップを再取得しました。
すべて正しいXMLを返すことを確認し、Search Consoleへ再送信した結果、サイトマップは正常に受理されました。

WordPressのSEOスパムを自分で削除した気になるのが危険な理由
今回のように、不正コードを自分で見つけて削除しても、別の感染箇所が残ることがあります。
侵入経路、バックドア、漏えいした認証情報まで確認しなければ、同じ改ざんが再発するおそれがあります。
似たコードが正規機能にも存在する
curl_init()、file_get_contents()、User-Agent判定は、正規のAPI連携や表示最適化でも使われます。
初心者が関数名だけを見て一括削除すると、問い合わせ、決済、更新、SEOなど正常な機能まで壊す危険があります。
見つかったファイルが侵入元とは限らない
今回の不正コードはテーマにありましたが、テーマ自体が最初の侵入口だったとは限りません。
古いプラグイン、盗まれた管理者・FTP情報、別サイトからの横展開、サーバー内の不正処理など、複数の可能性があります。
表示が直っただけでは復旧完了ではない
普通にサイトが表示されても、Googlebotだけが不正ページを受け取っていれば被害は続いています。
反対にGooglebotで直っても、管理者、Cron、データベース、別ファイルに再生成元が残っている場合があります。
- スキャン結果と実際の症状が一致しない
- 検索経由・スマホ・Botだけ表示が変わる
- 外部通信するPHPの目的を説明できない
- バックアップを戻しても再発する
- どのファイルが正規か判断できない

WordPressのSEOスパムを再発させない対策
再発防止には、侵入経路を塞ぐ対策と、未知の改ざんを早く見つける監視の両方が必要です。
セキュリティプラグインを入れるだけで終わらせず、変更の基準と外部からの表示確認を持ちましょう。
- WordPress本体・テーマ・プラグインを安全な最新版へ更新する
- 管理者、サーバー、FTP/SFTP、データベースの認証情報を変更する
- WordPressの認証キーと全ログインセッションを更新する
- 独自テーマの正常時ハッシュを保存し、変更を監視する
- 通常ブラウザとGooglebotの応答差を定期確認する
- アクセスログ、FTPログ、管理者操作履歴を一定期間保管する
特に独自テーマでは、正常な時点のファイルハッシュを保存しておくと、未知のマルウェアでも変更直後に気づきやすくなります。
外部監視で同じURLを通常UAとGooglebot UAから取得し、Content-Typeや本文ハッシュを比較する方法も有効です。
バックアップも、感染後に上書きされたものだけでは復旧に使えません。
日付の異なる複数世代をサーバー外へ保管し、復元前にバックアップ自体を検査してください。復元後はパスワードや認証キーを変更し、同じ条件で不正応答が再発しないことまで確認します。
WordPressのSEOスパムでよくある質問
WordPressのSEOスパムは「消えたように見える」で終わらせない
今回の実例では、サイト所有者が自分で不正ファイルを削除し、通常画面も正常に戻っていました。
しかし専門調査では、検索エンジンにだけ不正HTMLを返すコードが独自テーマ内に残っていることが判明しました。
重要なのは、自分が見つけた範囲だけで安全を判断しないことです。
症状の再現、正常ファイルとの比較、テーマ・プラグイン・uploads・DB・ログを横断し、駆除後も複数条件で再検証する必要があります。
自分で駆除したWordPressが本当に安全か今すぐ確認してください

画面が直った、スキャンが正常だったという理由だけで、完全駆除と判断するのは危険です。
クイックレスキューが残存調査から駆除、再発防止、検索エンジン向けの再検証まで対応します。
- スキャンは正常なのにGoogleの表示がおかしい
- 検索エンジンやスマホでだけ不正ページが出る
- 怪しいコードを見つけたが削除してよいか判断できない
- 自分で削除したが、本当に駆除できたか不安
- サイト全体とデータベース、侵入経路まで調査してほしい
- 万一復旧できない場合やマルウェア駆除できない場合は全額返金保証で安心
- 90日間再感染保証・動作保証で安心
- 初期費用・調査費用0円で安心
