Fail2banでxmlrpc.phpへの大量リクエストをブロックする方法

WordPress

攻撃されるとどうなるか

WordPressに対する攻撃の中でも、xmlrpc.phpは最も狙われやすいもののようです。かく言う私も経験が…。

この攻撃はxmlrpx.phpへ膨大な量のPOSTリクエストが送られ、結果DBがメモリ不足に陥ったりし、サーバーのリソースを枯渇させます。そしてサイトが閲覧不可能な状態になったりします。要するにDoS攻撃ですね。

pinbackの機能を悪用して反射型DoS攻撃の踏み台に使用されることもあるよう。

また、ブルートフォース攻撃(要するに認証のクラック)の対象にもされます。

WordPressは手軽な反面、十分な対策が事前に必要ですね。

xmlrpc.phpって?

サイト外部から投稿する際に使用されるもので、iOSやAndroidのアプリも利用します。

なので、消せばよいというものでもない。

対策法

①xmlrpc.phpを削除
根本的ではありますが、使用してるプラグインがあったり、外部から投稿をする場合は差支えがあります。その場合は②の方法が良いでしょう。

②.htaccessでアクセス制御
最上位のフォルダ(xmlrpc.phpがある)の.htaccessに追記する方法です。
具体的には、以下の文言を追記します。

<Files xmlrpc.php>
Order Deny,Allow
Deny from All
</Files>

ググると一番よく見る方法です。
悪くない方法ですが、アクセスの度にApacheに負荷がかかる気がします。

③攻撃元IPをFWで自動的にブロックする仕掛けを作る
CensOSなら、Fail2banで実現可能です。事前に定義した不審な挙動に該当するIPを一定期間(もしくは永遠に)FW側で自動的にアクセス遮断をします。

②の方法は比較的簡単ですぐに分かると思いますので、以下では③の方法を解説します。

ご自身の環境に合わせた(もしくは好みの方を)お使い下さい。

Fail2banの導入・設定

インストール

環境はCentOS 7を前提に話を進めます。

インストールは以下のコマンドで。

yum install fail2ban

設定作業

jail.localを作成

etc/fail2ban/jail.confにルールを記述しますが、これは直接修正せず同階層にjail.localを作成します。jail.localに記述した設定が優先され、記述していない箇所はjail.confに従います。

以下、設定例です。

# jail.conf

[DEFAULT]
ignoreip = 127.0.0.1/8
banaction = firewallcmd-ipset
destemail = xxx@xxx.com(通知メールアドレス)
sender = no-reply@xxx.com(通知の送信元メールアドレス)
mta = sendmail
action = %(action_mw)s

[xmlrpc]
enabled  = true
filter   = xmlrpc
logpath  = %(apache_access_log)s
bantime  = 21600
findtime = 600
maxretry = 10

以下、各項目を解説

[DEFAULT]は各ルール共通の設定です。
この場合、ignoreipからactionまでが共通の設定。

ignoreip
ルールを適用しないIPを指定。

banaction
ルールに該当するIPに対する挙動を指定します。firewallcmd-ipsetはjail2banフォルダのaction.dフォルダ配下にあるfirewallcmd-ipset.confで定義されたもの。該当IPのパケットをDROPするルールをfirewalldに指定の期間設定します。
(※デフォルトではDROPではなくREJECTですが、設定方法は後で解説します)

destemail
BANされた時の通知先メールアドレスを記述
sender
通知メールの送信元アドレスを記述
mta
sendmail, mail, postfixのどれかを記述

action
通知のアクションを指定。
%(action_mw)sは、BANされたIPのwhois検索の結果も含めて通知します。具体的にはjail.confに記述があるので参照のこと。また、当然ですがwhoisがインストールされていないとwhoisの検索結果が無い状態で通知が来ます。

[xmlrpc](名称は任意に設定)以下は個別の設定です。

enabled
trueにしないと機能しませんので、必ずtrueにします。

filter
filter.dフォルダ以下に検出するリクエストのパターンを個別のファイルで記述するのですが、その定義を指定します。ちなみに、この場合、filter.d以下にxmlrpc.confがあることになります(※後で解説)。
先に説明すると、filter、bantime、maxretryの定義に該当するリクエストがあると、bantimeの時間だけアクセスをBANする、ということになる。

logpath
アクセス記録の元となるログを指定します。この場合はApacheのアクセスログ。

bantime
該当IPをBANする時間を「秒」で記述

findtime
filterで定義したリクエストをカウントする時間を「秒」で記述

maxretry
findtimeの時間内にこの回数だけfilterに該当するリクエストがあるとBANされます

filter.d/xmlrpcを作成

検出するリクエストのパターンを記述します。上述のfilterの設定の基はこれになる。

# xmlrpc.conf
[Definition]
failregex = ^<HOST> .*\"POST [^\"]+xmlrpc\.php+[^\"]+\"
ignoreregex =

failregex
Apacheアクセスログから検出するパターンを正規表現で記述します。この場合、xmlrpc.phpに対するPOSTリクエストがあった場合を想定します。

action.d/iptable-common.localを作成

デフォルトではBANされたIPのパケットはREJECTされる設定ですが、これだと攻撃元に通知がいきますので、DROPする設定にかえます。
具体的にはaction.dフォルダの下にiptable-common.localを作成し、以下のように記述。

# iptable-common.local
blocktype = DROP

これで設定は完了です。

起動

以下のコマンドで起動します。
問題があればエラーが出ますので、メッセージを基に対処しましょう。

systemctl start fail2ban

状態を確認する際は、以下のコマンドで。
active(running)になっていることを確認しましょう。

systemctl status fail2ban

設定ファイルを変更した場合、以下で再読み込みします。

systemctl reload fail2ban

以上です。