2026年5月19日
2026年5月19日
WordPressにWAFを導入する方法:Cloudflare・ModSecurity・Wordfenceの選び方
WAF(Web Application Firewall)は、Webサイトへのリクエストの中身を調べ、SQLインジェクションやクロスサイトスクリプティング(XSS)、既知の脆弱性を狙う攻撃などを遮断する仕組みです。WordPress では、プラグインやテーマの脆弱性が公表されてから更新するまでの間の攻撃を減らす役割があります。
WAFはどこに置くかで3種類に分かれます。この記事では、それぞれの特徴と導入手順、あわせて設定しておきたいログイン試行の制限を説明します。各サービスの提供範囲とパッケージのバージョンは、2026年11月時点で公式ドキュメントを確認した内容です。
WAFの3つの種類
| 種類 | 例 | 検査する場所 | 向いている環境 |
|---|---|---|---|
| クラウド型 | Cloudflare | サーバーに届く前(DNSをクラウド側に向ける) | どの環境でも。サーバーの負荷を増やさない |
| サーバー型 | ModSecurity + OWASP CRS | Webサーバー(Apache・Nginx)の中 | VPS・専用サーバーなど、Webサーバーの設定を変えられる環境 |
| プラグイン型 | Wordfence | WordPress(PHP)の中 | 共用レンタルサーバーなど、サーバーの設定を変えられない環境 |
複数を重ねて使うこともできますが、同じ種類の検査を二重にすると、誤検知の原因を探すのが難しくなります。まず1つを選び、ログを見ながら調整してから、必要に応じて追加するのがおすすめです。
なお、レンタルサーバーの多くは、コントロールパネルでWAFを有効にできる機能を用意しています。利用中のサーバーにこの機能があれば、まずそれを有効にするのが手軽です。
方法1:Cloudflare(クラウド型)
Cloudflare を使うと、サイトへのリクエストはすべて Cloudflare を通ってからサーバーに届きます。WAFのルールは Cloudflare のダッシュボードで設定します。
プランごとに使える管理ルール(Cloudflare が用意するルールセット)は次のとおりです。
| ルールセット | Free | Pro / Business / Enterprise |
|---|---|---|
| Free Managed Ruleset | ○ | ○ |
| Cloudflare Managed Ruleset | × | ○ |
| OWASP Core Ruleset | × | ○ |
Freeプランの Free Managed Ruleset は、影響が大きく広く悪用されている脆弱性への対策に絞ったルールセットです。WordPress 向けのルールを含む Cloudflare Managed Ruleset を使うには Pro 以上のプランが必要です。
導入時の注意点です。
- サーバーへの直接アクセスを塞ぐ: サーバーのIPアドレスを知られていると、Cloudflare を経由せずに直接攻撃される可能性があります。サーバーのファイアウォールで、HTTP/HTTPS の接続元を Cloudflare のIPアドレスに限ると、WAFを迂回されにくくなります。
- 接続元IPの記録: Cloudflare 経由のアクセスでは、サーバーのログに Cloudflare のIPアドレスが記録されます。訪問者のIPを記録するには、Webサーバー側で Cloudflare のIPアドレス範囲を信頼する設定が必要です。
初期設定の流れはWordPressにCloudflareを設定する方法、WAFのルール設定はCloudflareのWAF設定で詳しく説明しています。
方法2:ModSecurity と OWASP CRS(サーバー型・Apache)
ModSecurity は Apache や Nginx に組み込んで使うWAFのエンジンです。攻撃を判定するルールには、OWASP が公開している Core Rule Set(CRS)を使います。ここでは Ubuntu 24.04 の Apache での手順を示します(Ubuntu 24.04 のパッケージの CRS は 3.3.5 です)。
1. インストールする
sudo apt update
sudo apt install libapache2-mod-security2 modsecurity-crs
sudo a2enmod security2
CRS の設定ファイルは /etc/modsecurity/crs/crs-setup.conf、ルール本体は /usr/share/modsecurity-crs/rules/ に置かれます。
2. まず「検知のみ」で動かす
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
grep -n "^SecRuleEngine" /etc/modsecurity/modsecurity.conf
# SecRuleEngine DetectionOnly となっていることを確認する
DetectionOnly は、攻撃と判定したリクエストを記録するだけで遮断しない動作です。いきなり遮断を有効にすると、管理画面での投稿の保存やプラグインの操作が止まることがあるため、最初はこの状態で動かします。
3. WordPress 用の除外ルールを有効にする
CRS 3.x には、WordPress の正常な操作を誤検知しないための除外ルールが含まれています。/etc/modsecurity/crs/crs-setup.conf の id:900130 の部分を探し、行頭の # を外して WordPress の行だけを残します。
SecAction \
"id:900130,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.crs_exclusions_wordpress=1"
設定を確かめてから Apache を再起動します。
sudo apache2ctl configtest
sudo systemctl restart apache2
4. 検知されるかを試し、ログを確認する
自分のサイトに、SQLインジェクションに見える文字列を付けてアクセスします。
curl -s -o /dev/null -w "%{http_code}\n" "https://example.com/?id=1%27%20OR%20%271%27=%271"
DetectionOnly ではこのリクエストは通常どおり 200 などが返りますが、Apache のエラーログに ModSecurity: Warning で始まる記録が残ります。
sudo grep "ModSecurity" /var/log/apache2/error.log | tail -n 20
詳しい記録は監査ログに出ます。場所は /etc/modsecurity/modsecurity.conf の SecAuditLog で確認できます。
5. 誤検知を確認してから遮断に切り替える
数日から1週間ほど、管理画面の操作(投稿の保存、メディアのアップロード、プラグインの更新など)やフォームの送信をいつもどおり行い、ログに正常な操作が記録されていないかを確認します。問題が無ければ遮断を有効にします。
sudo sed -i 's/^SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
sudo apache2ctl configtest && sudo systemctl restart apache2
遮断が有効になると、攻撃と判定されたリクエストには 403 が返ります。手順4の curl で 403 が返ることを確かめてください。誤検知が見つかった場合は、ログに出ているルールIDを手がかりに、そのURLやパラメーターだけを除外します。
ModSecurity の詳しい設定はApacheでModSecurityを使う方法、Nginx での導入はNginxでModSecurityを使う方法を参照してください。
方法3:Wordfence(プラグイン型)
サーバーの設定を変えられない共用レンタルサーバーでは、WAF機能を持つプラグインを使います。代表的な Wordfence は、無料版でもファイアウォールを使えます。
- 保護レベル: 「Basic WordPress Protection」は WordPress の読み込みと一緒にファイアウォールが動きます。「Extended Protection」は PHP の
auto_prepend_fileの設定を使い、WordPress や他のプラグインより先にファイアウォールを動かします。どちらも無料版で使えます。Extended Protection に切り替えるときは、Wordfence の画面に表示される手順に従います。サーバーによっては.htaccessや.user.iniの書き換えが必要です。 - 学習モード: インストール直後の1週間は学習モードで動き、サイトの正常なリクエストを覚えて誤検知を減らします。この間はファイアウォールのルールによる遮断が行われない点に注意してください。
- ルールの更新: 無料版のファイアウォールのルールは、有料版での公開から30日後に提供されます。
プラグイン型は WordPress と同じサーバーで動くため、攻撃の量が多いとサーバーの負荷が増えます。アクセスが多いサイトでは、クラウド型やサーバー型との併用を検討してください。
あわせて設定したい:ログイン試行の制限
WAFのルールは、パスワードを総当たりで試す攻撃(ブルートフォース攻撃)をすべて止められるわけではありません。wp-login.php への試行回数の制限もあわせて設定します。
Nginx を使っている場合は、limit_req で1つのIPアドレスからのリクエストの頻度を制限できます。次は Ubuntu 24.04 で PHP-FPM 8.3 を使う場合の例です。
# /etc/nginx/conf.d/wp-limit.conf(http コンテキストに読み込まれる場所)
limit_req_zone $binary_remote_addr zone=wp_login:10m rate=5r/m;
# サイトの server ブロックの中
location = /wp-login.php {
limit_req zone=wp_login burst=5 nodelay;
limit_req_status 429;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
# XML-RPC を使っていない場合だけ閉じる
location = /xmlrpc.php {
deny all;
}
rate=5r/mは1分あたり5回、burst=5は一時的に超えてよい回数です。超えたリクエストにはlimit_req_statusで指定した 429 が返ります。fastcgi_passのソケットのパスは、PHP のバージョンと環境によって違います。既存のlocation ~ \.php$ブロックに書かれている値に合わせてください。- Jetpack や WordPress の公式モバイルアプリなど、XML-RPC を使う機能がある場合は
xmlrpc.phpを閉じないでください。
設定後は sudo nginx -t で構文を確かめてから sudo systemctl reload nginx で反映します。Apache や共用サーバーの場合は、プラグインでログイン試行を制限する方法があります。詳しくはログイン試行回数を制限する方法を参照してください。
運用の注意点
- 検知のみで始め、ログを見て調整する: どの種類のWAFでも、誤検知で投稿の保存やフォームの送信が失敗することがあります。導入直後は検知のみ(または学習モード)で動かし、ログを確認してから遮断を有効にします。
- 独自の判定コードを functions.php に書かない: リクエストの文字列を正規表現で調べるような自作の判定は、正常な投稿本文やコメントまで遮断しやすく、すり抜けも起きやすい方法です。保守されているルールセット(CRS、Cloudflare、Wordfence)を使うほうが安全です。
- WAFは更新の代わりにならない: WAFは攻撃を減らす仕組みで、脆弱性そのものを直すものではありません。WordPress 本体・プラグイン・テーマの更新を続けてください。
- セキュリティヘッダーは別に設定する: クリックジャッキング対策などのHTTPヘッダーは、WAFとは別にWebサーバーで設定します。セキュリティヘッダーの設定方法を参考にしてください。
まとめ
- WAFはクラウド型(Cloudflare)、サーバー型(ModSecurity + CRS)、プラグイン型(Wordfence)の3種類。サーバーの設定を変えられるかとアクセス量で選ぶ。
- Cloudflare の Free プランで使える管理ルールは Free Managed Ruleset。サーバーへの直接アクセスも塞ぐ。
- ModSecurity は
DetectionOnlyで始め、CRS の WordPress 用除外ルールを有効にし、ログで誤検知が無いことを確かめてからSecRuleEngine Onにする。 - Wordfence は無料版でもファイアウォールを使え、Extended Protection で WordPress より先に検査できる。
- ログイン試行の制限は WAF とは別に設定する。