WordPressへのパスワード総当りやXML-RPC攻撃をfail2banで緩和するプラグイン「WP fail2ban」

wrench-in-hands_sizeXS.jpg

WordPress のログインパスワードに対するブルートフォース(総当り)攻撃や、XML-RPC 攻撃を fail2ban で緩和するプラグイン「WP fail2ban」を紹介しておきます。

正直、詳しい人でないとつまづくポイントが多い方法です。が、分かっている人向けに端折って書かせていただきます。

分からない場合は無理に今回の方法は使わず、.htaccess でIPアドレス毎にアクセス制御をかける方法(イタチごっこ)や、Wordpress の XML-RPC を丸ごと無効化する方法、XML-RPC のうち pingback 機能だけを無効化する方法などを検討するのが良いでしょう。

ただ、それらの方法だと大人の事情で不都合がある場合には、今回の方法も選択肢のひとつです。また、これら複数の策を組み合わせて防御を強化する方法もあります。

fail2banでWordpressのXML-RPCへの攻撃などを緩和する設定

概要としては、WordPress の XML-RPC は止めずに、WordPress へあるパターンでアクセスしてきたIPアドレスだけを fail2ban で BAN します。

Linux、syslog、WordPress、PHP、fail2ban、TCP/IP周りについて、一定以上理解している前提にて話しを進めていきます。

大まかな設定の流れは以下のとおり。

  1. WordPress XML-RPC API への攻撃などを syslog に書き出す WordPress 用プラグイン「WP fail2ban」をインストール
  2. fail2ban に syslog を読ませて適宜 BAN する設定をする

WordPressプラグイン「WP fail2ban」の導入

まず最初に、WordPress用プラグイン「WP fail2ban」をインストールします。

これは、WordPress XML-RPC へのアクセスなどを syslog に書き出してくれる「だけの」 単純な WordPress 用プラグインです。

プラグインの権限では fail2ban の設定までは変更できないので、手作業で次のような設定が必要になります。

プラグインインストール後は、プラグインディレクトリ以下の「wordpress.conf」を fail2ban/filters.d にコピーします。(権限に注意)

また、fail2ban の設定ファイルである「jail.local」は、こんな感じで設定してやります。

[wordpress]
enabled  = true
filter   = wordpress
# Ubuntu
# logpath  = /var/log/auth.log
# Cent OS
logpath  = /var/log/messages
action   = iptables-multiport[name=wordpress,port="80,443"]
maxretry = 10

(※Cent OS ではどう設定しても /var/log/secure に吐いてくれなかった…)

logpath は、環境ごとに適切な場所を指定すればOK。

実際には findtime、bantime、maxretry あたりにも「賢い値」を設定する必要が出てくる可能性が高いです。攻撃者が再攻撃を諦めるどうかはこの設定値にかかってきます。(後述の累犯者設定と組み合わせるのが良い。)

ちなみに、このプラグインは初期状態だと、WordPress へのログイン失敗だけを PHP の syslog() 関数で書き出しますが、wp-config.php に設定を追加すれば、XML-RPC のピンバック要求やユーザー名列挙要求、特定ユーザーでのログイン拒否も syslog へ書き出す事ができるようになります。

wp-config.php への設定例は以下です。

// LOG_AUTHPRIV が使えるなら望ましい(/var/log/secure とか)
define('WP_FAIL2BAN_AUTH_LOG', LOG_AUTHPRIV);

// XML-RPC pingbacks フラッド攻撃対策
define('WP_FAIL2BAN_LOG_PINGBACKS',true);

// XML-RPC 経由でのユーザー列挙をブロック
define('WP_FAIL2BAN_BLOCK_USER_ENUMERATION',true);

設定と挙動の関係については、公式FAQだけでなく、プラグインのソースにも目を通しておいた方が確実と思います。

最後に fail2ban サービスをリスタートして、エラーが出なければ設定完了です。

ハマりどころ

ちなみに、僕の環境では wp-config.php に「WP_FAIL2BAN_AUTH_LOG」を設定しても、/var/log/secure にログを吐かせる事はできませんでした。

ということで、もし嵌るとするなら syslog への出力周りと、あとは動作検証方法や攻撃手法の解析周り、と思います。

XML-RPC pingbacks 対策なら別手法が楽かも

とりあえず xml-rpc.php 宛に大量の pingback 要求が投げられてサーバーのメモリが不足している。というレベルであれば、今回の方法でなく XML-RPC pingbacks だけを停止した方が手軽で確実でしょう。今回の方法だとBAN判定までのわずかな間にも多少は踏み台になるため、pingbacks を停止した方がより、周りに迷惑を掛けずに済むと思います。

ちなみに今回の方法で注意すべきは、fail2ban のBAN判定条件です。

手を抜いて初期値なんか使おうもんなら、勘のいい攻撃者はそういう所までお見通しなので、その閾値をくぐり抜けられるよう1IP当たりの攻撃頻度を下げ、かつ、攻撃元を分散することで攻撃量を維持してきます。

このあたりは攻撃者に「このサーバは使えねーな」と思わせる腕の見せ所でして、必要なら他の防御策も合わせて使うのが良いと思います。

というあたりが、今回の方法が万人向けではない。という理由にはなってきます。

攻撃手法の確認にはパケットキャプチャが便利

繰り返しますが、今回のプラグイン「WP fail2ban」は、ログインの失敗、および一部の XML-RPC 要求などを、ある条件の場合だけ大雑把に syslog に書き出してくれる機能しか持っていません。

そのため、「WP fail2ban」がログ出力しない XML-RPC への攻撃、にはなんら効果が無い事は理解しておく必要があります。魔法の杖じゃない。ということです。(以下はログが吐かれないアクセス例)
WPfail2banToMitigateXmlRpcAttack_2_sh

という事で、tcpdump や Wireshark などのネットワークキャプチャを使って攻撃内容を把握することも肝要であると個人的には思います。

なお、fail2ban でBANされた攻撃者が攻撃を継続した場合、 攻撃者はSYN_SENT の状態で待たされ、TCP再送処理を走らせるケースがほとんどでしょう。
WPfail2banToMitigateXmlRpcAttack_1_sh

こういうのも自分の目で確認しておくと、あー、ちゃんと動いてるなー。と安心できると思います。

fail2ban の累犯者向けBAN設定がお便利

fail2ban のBAN設定の加減が悩ましい場合は、初犯には緩めにしておき、執拗に攻撃を繰り返してくる輩にだけ、より厳しい長期BANを喰らわせる、という方法もあります。

実効的な対策は取りつつも、運用上のミスには優しい。といういい塩梅を狙うわけです。

参考・情報:

※2015/2/16 文章ブラッシュアップ

Hatena Pocket Line

コメントを記入