はじめに
以前、Theme のリニューアルをお手伝いした WordPress のメンテナンスを承った。PHP はそれほどでもないが、CVE(脆弱性)報告数がスパイクしているので、さぞかしプラグイン等のアップデートが大量にあるんだろうなと想像しつつ、サイトにアクセスしたところ…
重っ!!
以前とは比べ物にならないほどのサイトレスポンスの劣化。確かに重い画像は多いけど、こんなに遅いのはありえない。
もしかして、攻撃されてサーバがパンパンになってるじゃないの?!と思ってログを漁ってみたところ、めちゃめちゃ攻撃されていた。漏洩等のインシデントは起きていなかったけど、負荷がかかりすぎてサイトがちょっと落ちてたりした模様。
WordPress のような有名 CMS は、AI などなくとも、常に攻撃に晒される。
前回メンテ時に施した最低限のセキュリティ対策は機能していたようだけど、どうやら攻撃モードが変わっているようで、最近攻撃され慣れている私から見ると、現モードでは不十分。徹底的に撃ち落としてやる!!と意気込んで対策してみた。
なお…
WordPress は攻撃の標的になりやすいので、もう使うの止めようかな?というのは、ちょっと待った方が良い。他の CMS だって攻撃されるし、ちゃんと対策すれば、使い方によるけど、WordPress はむしろ安全な部類では?と思う。逆に WordPress でちゃんと対策できないのであれば、他でも対策はできない。箱替えに意味は、あんまりない。
環境
- さくらサーバ
- PHP 8.3
- WordPress 7.0
攻撃サマリー
クライアント情報なので実数は避けるが、とんでもない数だった。ピーク時は、正常アクセスの数千倍。
発信元国別上位
| 国 | % |
|---|---|
| アンドラ | 82% |
| オランダ | 5% |
| フランス | 2% |
| ブルガリア | 2% |
| シンガポール | 1% |
| ドイツ | 1% |
| アメリカ | 1% |
| 日本 | 1% |
| その他 | 1% |
いずれもデータセンターやホスティング事業者の IP であり、一般家庭・オフィス回線ではなかった。
アンドラってどこ?と調べたところ、ピレネー山脈にある人口8万人程度の小さな国だった。高地はサーバの冷却が効率的とかなのだろうか?トゥールーズからバルセロナに向かう途中にあるらしいので、いつか行ってみたい笑
攻撃面
- 管理ログイン (
wp-login.php) - REST API ユーザ列挙 (
/wp-json/wp/v2/users) xmlprc.php- 機微ファイル (
.env/.git/wp-config.php/database.ymlなど) - プラグイン脆弱性探索
- RCE 探索
などなど。
認証突破、踏み台、乗っ取りなどが主目的の攻撃。
攻撃トレンドを把握
Gravity SMTP / CVE-2026-4020(2026年5〜6月)
- メール送信プラグイン Gravity SMTP の REST エンドポイント
/wp-json/gravitysmtp/v1/tests/mock-dataがpermission_callback不備で未認証アクセス可能となり、APIキー/OAuthトークンが窃取可能 - Wordfence 観測で 5月以降1,700万件の攻撃、6/7 にピーク(単日400万件超ブロック)、6/11 まで継続
このプラグインは利用していないが、無差別スキャンに巻き込まれ、一時的にサイトが落ちていた模様。すぐに諦めず、徹底的に探索するんですね。おぉ怖。
さくらインターネットの状況
特段新しい情報はなかったが、作業時に確認したところ、落ちてるサーバもあるみたいなアナウンスがあった。さくらサーバさんには頑張っていただきたい。
REST ユーザー列挙
- 「REST列挙 → 収集ID に対する分散総当たり」の典型パターン
これは、常態化している。
基本方針
漏洩等の被害は出ていないが、サーバ負荷がかかっているということは、PHP で防御しているということなので、エッジアクセスで撃ち落とせば良い。
だったら、さくらの WAF や国外 IP フィルタを有効にすればおしまいでは?と思ったのだけど、
WAF
- 検知のみの監視モードがなく即ブロック
- 検出ログが前日分のみで調整が遅い
- 誤検知救済措置がない
ということで利用は見送り
Admin の国外 IP フィルタ
有効にしたら、日本国内 IP からもアクセスできなくなった。ホワイトリスト方式のようだけど、そのリストがメンテナンスされていないのか、どこにも記述はないけど国内であっても VPN は認めないなどのポリシーがあるのかも知れない。VPN は Location 偽装ツールではなく、セキュリティツールなので、VPN 認めない!みたいなポリシーがあるとしたら、いかがなものかと思う。個別に IP を設定できるが、やり方が間違っているのか、それもうまく機能しなかったので、アクセス手段がなくなってしまった。
いずれにしても、アクセスできないし、誤爆が多そうな雰囲気なので、利用は見送り
それを踏まえた方針
どちらも使えないので、地道に調べて塞いでいく。基本的には、.htaccess で撃ち落とす。
- 不要プラグインを削除し、攻撃面を減らす
- 常時使用しないもの(メンテ系等など)は、無効化ではなく削除
- 利用していないことを確認して(利用しないようにして)
.htaccessで遮断- PHP で遮断しない
- PHP で守る系のプラグインは、作り直す(自作)
- 攻撃を受けやすいプラグイン(画像処理系など)は、作り直す(自作)
- ChangeLog などを漁って、どんな攻撃をされているかを調べて迂回する
- DB の掃除
- 攻撃されても漏れて困るデータがなければ良い発想
- WordPress に限らない常識的な対応を行う
対応を全部書いても地味なので、以降かいつまんで。
xmlrpc.php の遮断
セキュリティリスクが高いので、無効化が推奨されている。
その方法としてよくあるのが、
-
Disable XML-RPC API等のプラグインによる無効化 - テーマの
functions.phpでのフィルター
などだが、これだと PHP まで届いてしまうため、却下。
対象 WordPress では、利用していないので、.htaccess で完全遮断。
RESTユーザー列挙の遮断
こちらは、今回の対応ではなく前回の対応になるが、フロントで API を使わず WP_QUERY(サーバ側生成)を使うように作り変えたため(不具合起因)、公開されているフロントエンドは REST API を利用していない。
元々 401 で拒否していたが、これは毎回 WordPress + MySQL を起動して処理していたため、エッジ拒否。
という訳で、未認証の users エンドポイントは完全遮断。
アンドラからの攻撃は全てここだったので、これで攻撃の 82% を遮断できたことになる。後日ログで、きちんと遮断できていることが確認できた。
自作プラグイン
攻撃面を減らすためにプラグインを整理したのに、プラグインを増やすことには抵抗があったが、機能は Minimal で攻撃されづらいように注意して 2 つプラグインを作成した。
ログイン URL 秘匿
SiteGuard などの有名プラグインは、ログイン URL を Rename してくれるが、デフォルトの wp-login.php の保護が PHP 層であり、サーバ負荷はかかってしまう。
なので、
- 秘密パス →
wp-login.phpを内部リライト -
wp-login.phpへの直接アクセスは 403
になるように自作。ログインへのリダイレクトで秘匿 URL を辿られないように注意。
画像最適化
これは攻撃には直接関係ないのだけど、どうもサーバ負荷の影響でリサイズに失敗している画像などが散見され、レスポンスに影響を与えていた。リサイズ済みの画像も、サイズが大きいので WebP 化してさらに軽量化をはかりたい。
しかし、既存のプラグインはやたら攻撃されているものが多いようなので(確認当時 Converter for Media は未認証 SSRF の CVE があって戦ってる最中だったり。)、同じ攻撃を迂回するようなプラグインを作成。
- REST/管理UI/外部通信を持たない
- SSRF/CSRF/REST認証の脆弱性クラスを構造的に回避
という設計で自作。
DB の掃除
WordPress でよく利用される Contact Form 7 + Flamingo などのフォーム機能の、漏れたら困る個人情報を含むデータが、現在は使っていないため確認すらできないが、 DB に大量に残っていたので、 csv に吐き出して削除した。
プラグインを削除する時に、データも消す?などの問合せはなかったような気がする。消してねなどのメッセージはあったかも知れないがたぶん見落とした。ちょっと不親切かなと思う。
その他には、SMTP の設定とか、使ってないけど残ってるデータは、ちょいちょいあるので丁寧に確認して全部消した。
これで残る漏れて困る系のデータは管理ユーザだけだが、これは休眠ユーザは削除、Administrator は限定する、パスワードを強力なものにする程度。
まとめ
- WordPress がめちゃめちゃ攻撃されていたので、徹底的に撃ち落とした
- ただし、今後、より洗練された新しい攻撃は開発されると考えるべき
- 暫定アイアンドーム
- 今後突破されたとしても、漏れて困るデータがないようにした
- WordPress は攻撃に晒されやすいが、同時に防御も割とこなれている
- ただし、PHP 層での防御が主、という印象
対策方針としては、
- ログから攻撃面を特定し、実装と照らし合わせ対策優先順位を決定
- プラグインは本当に必要なもの以外は削除(無効化ではなく削除)
- プラグインを自作する場合は、既存類似プラグインがどのような攻撃を受けているかを分析して設計
- DB の残留データには注意
という感じでやれば良い。
なお、サイトレスポンスは、画像最適化もやったが、他にもやった。Lighthouse などで診断されるものは、WordPress の場合、比較的簡単に対策ができ、レスポンス(LCP)は 1/8 くらいまで速くできた。今後、うちにメンテナンス出さなくても良いよというくらいまで徹底的にやってしまったので、次にメンテナンス依頼が来るのは、私にお小遣いあげたくなったらくらいかも。
今回セキュリティ対策(とレスポンス最適化)などをやってみて、このあたりは「非エンジニア + AI」ではなかなか手が出ないところで、エンジニアの知見が活きるカテゴリなのかなと思った。結果がすぐ見えるし、楽しい。
実務的なセキュリティ対策は、強い権限が必要になったりするため、大きな企業では、末端のエンジニアにまで回って来づらい。しかし、コーディングなんか AI がやってくれるこのご時世、育成観点では、常に山程あるであろう攻撃の痕跡を元にして、対策や設計を考えるなどの、嗅覚を養う訓練が必要だろう。必要に応じてマスキングしたログだけ与えれば、権限与えずともローカルでできることが多いだろうし。
会社がやってくれない!という若者は、自分で WordPress を Hosting してみれば、すぐに誰かが、アンドラあたりから攻撃してくれるので、それで実験すれば良い。
うちの WordPress も診て!という人がいたら気軽にお声がけを。
(おしまい)