botによる WordPress への脆弱性スキャンをブロックする

Alibaba Cloud ESA を導入しトラフィックログ、セキュリティイベントを見ていると HTTPS Status Code で 500 が約2%あることに気づきます。 攻撃 bot が 脆弱性スキャンを行った結果であることがわかりました。。  直ちに侵入されるわけではありませんが、将来PHPに脆弱性が出た瞬間に突破されるかもしれませんので Apache のレイヤーと Alibaba Cloud ESA のレイヤーの2つのレイヤーで多層的に対策を施すとします。

Apache ログにおける Status Code 500 のサンプル

Apacheのログだとこんな感じです。

access_log
163.181.92.157 - - [09/Oct/2026:19:07:43 +0800] "GET /wp-includes/widgets/class-wp-widget-rss.php HTTP/1.1" 500 5365 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
163.181.92.152 - - [09/Oct/2026:19:07:44 +0800] "GET /wp-includes/widgets/class-wp-widget-rss.php HTTP/1.1" 500 5365 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
163.181.92.150 - - [09/Oct/2026:19:07:54 +0800] "GET /wp-includes/widgets/class-wp-widget-search.php HTTP/1.1" 500 5365 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0"
163.181.92.158 - - [09/Oct/2026:19:07:55 +0800] "GET /wp-includes/widgets/class-wp-widget-search.php HTTP/1.1" 500 5365 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0"
163.181.92.236 - - [09/Oct/2026:19:08:36 +0800] "GET /wp-includes/widgets/class-wp-widget-links.php HTTP/1.1" 500 5365 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15"

ログで 500 エラーになっているリクエストを見ると、すべて以下のようなパスに直接アクセスしています。

  • /wp-includes/widgets/class-wp-widget-rss.php
  • /wp-includes/class-wp-phpmailer.php
  • /wp-includes/cache.php
  • /wp-includes/template-loader.php

これらはWordPressの「システム内部のプログラム(クラスや関数を定義するファイル)」です。通常、WordPressのトップページ(index.php)などを通じて読み込まれる前提で作られています。

攻撃ボットがこれらのファイルを直接URLで指定(GET /wp-includes/...)して実行しようとすると、必要な関数や変数がロードされていないため、PHP側で fatal error(未定義関数の呼び出しなど)が発生し、Apacheが 500 Internal Server Error を返しています。

つまり、「サイトに問題がある」のではなく「攻撃者が存在しない使い方で内部ファイルを直接叩いたため、PHPがエラーで落ちた」状態です。

ログに出力されている 163.181.92.150 や 163.181.39.x などのIPは、Alibaba Cloud ESA のエッジサーバー(のIP)です。

ボットはESA経由でアクセスしてきていますが、User-Agent(Mac、Windows、Firefoxなど)を様々に偽装しながら、WordPressに脆弱性がないかをシラミつぶしに探す自動スキャンを実行しています。

500エラー自体はPHPが不正なリクエストを拒否して終了した結果ですが、毎秒のようにリクエストが届くとPHPプロセス(Apache/php-fpm)が無駄に起動し、サーバーのCPU・メモリを消費します。

PHPを起動させないようにするために、Alibaba Cloud ESA のレイヤとWebサーバー(Apache)のレイヤでブロックします。

どちらか片方だけでも構成可能です。  セキュリティだけを考えると同じ役割、目的でも様々な場所で多層に防御することは非常に有効です。 なので今回は2つのレイヤで同じ目的(PHPファイルへの直接アクセスの禁止)の設定を実施します。そうすることでどちらかで何か問題が起きたり、人間のミスで一時的に開放されても、防御は有効な状態を継続できます。

Apache での設定

wp-includes への直接アクセスを遮断(Apache設定)します。 WordPress公式でも推奨されている設定です。

.htaccess に以下を追加すると、外部からの内部ファイル直接参照をPHPまで届かせずに 403 Forbidden で即座に弾くことができます。 

もともとある設定とのマージや書き方に困った場合、内容を理解したい場合は生成AIに聞くと懇切丁寧に教えてくれます。 昔は Apacheのサイトにあるドキュメントを読んでよくわからんなーとか試行錯誤したものですが今は本当に便利になったと思います。 その分、馬鹿になっている気分にもなりますが・・。

.htaccess
# wp-includes への直接アクセスをブロック
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule ^wp-includes/.*\.php$ - [F,L]
</IfModule>

設定後、status code 500が発生しなくなることを確認し、設定は終了です。

Alibaba Cloud ESA での設定

Alibaba Cloudのコンソールにログインし、 ESA の Security > WAF の画面に移動します。

Custom Rules から “Create Rule”を実行します。

“Create Rule”からルールの作成を行います。 私が使っている無償の ESA では正規表現が利用できないため、2つのルールを作成します。  有償版なら”/wp-includes/*.php”の1つで済むと思います。

  • Rule Name :任意のルール名
  • If requests match..:
    • 1つ目のルール  (”/wp-includes/”から開始される、かつ)
      • Field: URI
      • Operator: starts with
      • Value: /wp-includes/
      • Case: Case-insensitive
    • 2つ目のルール (”.php”で終わる)
      • Field: URI
      • Operator: ends with
      • Value: .php
      • Case: Case-insensitive

作成したルールがリストに表示されればOKです。

テストします。 意図的に “/wp-includes”配下にWebブラウザからアクセスします。
https://www.bigriver.jp/wp-includes/block-patterns/query-offset-posts.php](https://www.bigriver.jp/wp-includes/block-patterns/query-offset-posts.php

Alibaba Cloud ESA が応答する以下の画面が表示されれば期待通りの動作となります。 エラーは画面はカスタマイズも可能です。

ちなみにESAでのブロック設定を実施する前は、以下のApacheから 403 応答が返ります。 

これで Apache レイヤーと Alibaba Cloud ESA レイヤーの2か所での多層防御の完成です。

以上