2014年3月15日土曜日

WordPressのpingback機能を悪用するDoSに対応しよう

みなさんこんにちは。

ブログシステムというよりもCMSと言ったほうがいいWordPressですが、pingback機能を悪用したDoS(サービス妨害攻撃)が横行していて、WordPressサイトの運営者は意図せずDoSの加害者になってしまう可能性があること、またすでにこの機能を悪用されて踏み台にされてしまったサイトが .JP ドメインにも多く存在している( 「DoSの踏み台にされているJPドメインのWordPressをまとめてみた」より )という状況があるようです。

この記事を書いているのはBloggerで私には直接関係ないように見えますが、まあWordPressのサイトなんて2個3個と持ってたりするわけでして、記事を更新しない筆不精っぷりはともかくとしても、人様に迷惑をかけることは避けたいというところで、嫌々(?)対応したところです。

そもそも WordPress の pingback 機能とは


一言で言えば、他サイトへのリンクを張った際にリンク先のサイトに通知する仕組みです( 日本語のpingback仕様はこちら )。

日本でブログが使われだした黎明期にブログの記事の間で「トラックバック」を飛ばしあうことが一時期流行ったのですが、「トラックバック」はSPAMに悪用されるケースが後を立たず廃れてしまいました。その代替機能としてSPAMに強いとされるpingback機能が有名ブログ/CMSエンジンに実装されてきました。が、最近はあまり使われていない機能のような気がします。

なぜ pingback 機能への対応が必要なのか


このpingback機能ですが、利用する際にはIDやパスワードのような認証機構を必要とせず、リンク元URL(ソースURI)とリンク先URL(ターゲットURI)の2つの情報でpingbackを利用することができます。

もちろん2つのURLが正当なものかどうかは双方のサーバで確認されるわけですが、正当なpingbackリクエストであるかどうかを確認するのにもサーバ上の資源を消費するわけで、多数のサイトから攻撃先サイトへのpingbackを行うことでDoSを成立させようというのが目論見のようです。

この問題について対応せずに放置しておいても運用しているサイトがSPAMだらけになるといといった目に見えた被害は出ないのですが、踏み台にされて攻撃に加担してしまうというのは残念なことです。「サイバーノーガード戦法」的な考え方も存在するのでしょうけれども、あまり褒められたものではありません。

具体的に対応するのはどうしたらよいのか


WordPressのpingback機能はXMLRPCという仕組みを使って実装されています。このXMLRPCはリモート投稿などにも使われていますが、問題となる機能を無効化するというのが対応の基本になります。実際には複数のアプローチがありますが、標準の設定画面では対応しきれない状況です。有効な手段を何個か紹介します。

Disable XML-RPC Pingback プラグインを導入する


pingback機能を無効化するプラグインが公開されているので、これを導入するという方法です。本質的にはうまく機能しそうな感じですが、「機能を無効化するために拡張機能をインストールする」という、「架空請求会社にあえて連絡してみる」的な気持ち悪さが残るのが難点です。

設定ファイル wp-config.php にpingback無効化設定を追加する


私が採用した方法で、「設定ファイルを編集する」という古典的な方法です。プラグインを入れるのと本質は変わらないのですが、プラグインと設定ファイルの差にこだわる人にはよいかもしれません。サーバ上のファイルの内容を編集する必要があるのですが、WordPressの初期導入時にこのファイルを編集する操作を行うので、このオペレーションに困るという例はないものと信じたいところです。

追加するのは、ファイルの末尾で、
add_filter( 'xmlrpc_methods', 'Remove_Pingback_Method' );

function Remove_Pingback_Method( $methods ) {
   unset( $methods['pingback.ping'] );
   unset( $methods['pingback.extensions.getPingbacks'] );
   return $methods;
}
という内容を書き足します。サイトによっては、「テーマの functions.php に書き加える」と説明されている場合もありますが、対応範囲の抜け漏れを防ぐために、サイト(とWordPressでいう「ネットワーク」)全体に波及するところに書くのが大切です。

また、私が対応した環境では add_filter の2つめの引数にクロージャ(無名関数)で指定するやりかたではうまく機能せず、また、
add_filter('xmlrpc_enabled', '__return_false');
としても本当に効いているか怪しかったので、この記述をしています。また蛇足ですが、XMLRPC全体を無効化するのであれば、
add_filter('xmlrpc_methods', '__return_false');
とするのが良いかと思います。一般的な構成であれば設定は即座に反映されるので、ApacheなどのWebサーバを再起動する必要はありません。

この方法では、XMLRPCのうち問題となるpingback機能だけを無効化することができるので、リモート投稿などXMLRPCの他の機能への影響がすくないというメリットがあります。もちろん WordPress 本体での対応が進んで再びpingback機能を有効にする際には、該当部の記述を削除することで本来の設定に戻すことができます。

xmlrpc.php へのアクセスをWebサーバで禁止してしまう


ここまではWordPress上での対応策ですが、そもそもWebで動くシステムなので、Webサーバでアクセス制御をかけてしまうというアプローチもあります。WordPressでXMLRPCを処理するのは xmlrpc.php なので、Apacheの場合だと例えば
<ifmodule mod_alias.c>
    RedirectMatch 403 /xmlrpc.php
</ifmodule>
として 403 を返してしまうようにしたり(この場合はxmlrpc.phpのパスの確認が必要です)、
<files xmlrpc.php>
    Order Deny, Allow
    Deny from all
</files>
とアクセスを禁止してみたり
<files xmlrpc.php>
    Order Deny, Allow
    Deny from all
    Allow from 192.168.12.34
</files>
特定の状況に合致する際にアクセスを許可するようにしてみたりといった設定で、回避することができそうです。

この方法は場合によってはWebサーバの管理者に設定変更を依頼する必要があったり、XMLRPC全体についてアクセス制御するため機能毎で許可不許可を使い分けるということができないのが難点です。

そもそも xmlrpc.php のファイル自体をどうにかしてしまう


XMLRPCの機能を全く使わないという前提で、xmlrpc.php ファイルそのものを削除したり、chmod でパーミッションを変えるという対応も成立しそうですが、WordPressのアップデート時にトラブルになるのでファイルそのものに働きかける対応は行わないほうが無難です。

対応が有効に働いているか確認しよう


ここまでは、DoSへの対応方法のお話でしたが、実施した対応がうまく働いているのか検証する必要があります。「対応したつもりだけど、作業にミスがあり効いていなかった」というのは残念すぎます。

今回のpingbackについては、実際にリクエストを行うのが良いのですが、テストデータを作って curl で送信してみるのがわかりやすいところだと思います。パラメータとか省いちゃってますが、
$ curl -d '<?xml version="1.0"?><methodCall><methodName>pingback.ping</methodName></methodCall>' http://(WordPressサイト)/xmlrpc.php
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>0</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string></string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>
$
という結果が帰ってきた場合には「未対応」の状態で、DoSの踏み台にされる可能性がある状態です。wp-config.php やプラグインで対策が有効になっている場合には
$ curl -d '<?xml version="1.0"?><methodCall><methodName>pingback.ping</methodName></methodCall>' http://(WordPressサイト)/xmlrpc.php
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>-32601</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>server error. requested method pingback.ping does not exist.</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>
$
と、「pingback.ping なんてメソッドないよ!」という状態になります。Apacheでアクセス制御した場合にはそもそも応答が帰ってきませんが、このようにして、実施したDoS対策が機能しているのか確認するのが大切です。

せっかくサイト運営するのだから、テーマデザインや広告収入の目算だけでなく、こういったところにも配慮して息の長い活動をし、また日本のWordPressコミュニティも迅速にこういった情報を公開していたりすると非常に美しい気がします。

Bloggerメインで台無し感漂う私も、「Ubuntu magazine vol.10」で「CentOSユーザへのUbuntu招待状」という記事を書いた際にWordPressを取り上げましたので、今回の説明がささやかな恩返しにでもなれば幸いです。