WordPressのhtaccessを編集するときにちょっち注意したい+α

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
やっぱ跡部様の方が圧倒的だわ

おまとめ三行

xmlrpc.phpにハンパないアクセスが来た
いつでも勝者は跡部様だぜ
じいさん二度びっくり

+αとか言っておきながら、実はそっちの方が本題だったりするのですが……。

先日、Wordpressで動かしてるうちの会社のサイトが攻撃を受けちゃいましてね……まあ、対策自体はそこまで大変なものではなかったのですが、その際、htaccessの編集で初めて知ったことがあったもんで、せっかくだからその情報を共有しておこうかなと。そんな次第です。



xmlrpc.phpにハンパないアクセスが来た

xmlrpc.phpというファイルに大量のPOSTが来た結果、それでウェブサーバーのCPUやDBの接続数が活動限界に達したっていうのが、今回やられたことです。

うっかりサーバーが落ちちゃったんで何が起きたんだろうと思ってログを見てみたら、こんな感じのアクセスが大量にあった。

185.11.144.82 – – [25/Apr/2015:13:36:20 +0900] “POST /xmlrpc.php HTTP/1.0” 200 370 “-” “Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)”

もうとにかくいっぱい来てた。同じIPアドレスから。登録した覚えのない出会い系サイトから来るスパムメールよりもいっぱい来てた。一ヶ月くらい放置した後の郵便受けの中のチラシよりもいっぱい来てた。バレンタインデーにテニプリの跡部様宛てに届くチョコよりもいっぱい……いや、もしかしたら跡部様宛てのチョコの方が多いかもしれん。さすがは跡部様だぜ。いつでも勝者は跡部様だぜ。

とりあえずそんな感じでサーバーが瞬殺されてしまいまして……調べてみたところ、このxmlrpc.phpってのはかなり攻撃の対象にされてるみたいです。「Wordpress xmlrpc.php」とかでググるといっぱい情報が出て来る。簡単に言うと、xmlrpc.phpはピンバックの送信などに使用するファイルで、ここにデータを大量POSTすることで任意のサイトに大量にピンバックを送信することができちゃう。そこで悪意のある第三者は、適当なサイトのxmlrpc.phpを踏み台にして、任意のサイトに攻撃を仕掛けたりするわけですね。あまりよく分かってないんで詳しい説明はできないです。詳細な内容が知りたければ、すみませんが各自ググってください。

まあ詳細が分からなくても、xmlrpc.phpに大量のPOSTが来るのが原因だってことだけ分かってれば、対策は打てます。



xml-rpcを無効にする

対策はいくつかやり方があるようですが、たぶん一番簡単なのはプラグインを使うこと。

Disable XML-RPC Pingbackっていうプラグインを使うと、xmlrpc.phpによるピンバック送信機能を無効にすることができます。よって、ピンバック大量送信もできなくなると。

プラグインをインストールして有効化すれば一発ですが、このプラグインの中身は10行くらいしかコードがないんで、functions.phpとかに自分で書いちゃっても良いかもですね。

add_filter('xmlrpc_methods', 'sar_block_xmlrpc_attacks');

function sar_block_xmlrpc_attacks( $methods ) {
  unset( $methods['pingback.ping'] );
  unset( $methods['pingback.extensions.getPingbacks'] );
  return $methods;
}

add_filter('wp_headers', 'sar_remove_x_pingback_header');

function sar_remove_x_pingback_header( $headers ) {
  unset( $headers['X-Pingback'] );
  return $headers;
}

これをfunctions.phpに書いとけば、上記のプラグインを有効化したときと同じ状態になる。



アクセス自体を無効にする

上のプラグインを入れれば確かにピンバックの大量送信は防げるんですが、サーバーへの負荷は減らない場合がある。うちはそうでした。プラグインを有効化したからこれで安心だーとか思ってたら、数時間後に再びサーバーが落ちてしまい、じいさん二度びっくり。

結局のところ、ピンバックが送信されないだけで、xmlrpc.phpへのアクセス自体は防げていなかったってことなんですよね。

なので、こうなったらもう、アクセス自体を無効にしてしまおうじゃないかと。

.htaccessにこんなのを書いとけば、xmlrpc.phpへのアクセスを完全に遮断することができます。

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

これで、いくらPOSTが送信されてきても403エラーを返すようになる。

ただ、こちらのjunkpotてくなメモさんによると、401や403を返すだけだと、攻撃自体は止まないことがあるみたいです。まあアクセスをシャットアウトしてるんだから、どんだけ攻撃されたところで基本的には問題ないと思うのですが、でもいくら大丈夫とはいえアクセスされ続けるのは気持ち悪い、だからアクセス自体止めてもらう方向に持って行きたいって場合は、404エラーを返すようにする方が効果的みたいです。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

//以下の二行を追加
RewriteCond %{REQUEST_FILENAME} xmlrpc\.php$
RewriteRule .* / [R=404,L]

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

これでxmlrpc.phpへのアクセスは全て404エラーになります。

ただし気をつけなきゃいけないのは、xml-rpcが機能しなくなるので、不正な攻撃だけじゃなく、自分が正当に使用している機能とかも使えなくなってしまう。例えば管理画面からではなく、アプリとかを使って記事を投稿する場合などもこのxmlrpc.phpは働くらしいんですが、そういう機能が使えなくなってしまう。

なので、本当にアクセスを禁止しても良いかどうかは要相談って感じですね。全アクセスを禁止するんじゃなくて、特定のアクセスはホワイトリスト化するとか。例えば自サーバーからのアクセスだけは許可したいとかだったら、こうですね。

RewriteCond %{REQUEST_FILENAME} xmlrpc\.php$
RewriteCond %{REMOTE_HOST} !^localhost$
RewriteRule .* / [R=404,L]

上記のlocalhostのように、許可したいアドレスなどがあればどんどん追加していけば良い。調べてみると、日本からのアクセスだけは許可したりとかいろいろやっている参考文献も多く見つかるんですが、僕はめんどかったんでとりあえず上記のようにlocalhost以外は禁止にしちゃいました。今のところ問題は起きてないです。



WordPressのhtaccessは勝手に書き換えられることがある

これは不正な攻撃によって、という意味ではなくて、例えばプラグインを有効化したときにもhtaccessは書き換わることがあります。なので、うっかりしているとせっかく自分で書いた404エラーなどの記述が消えてしまう。

Wordpressのhtaccessを見ると、こんな感じのことが書かれている。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

実はこの「# BEGIN WordPress」と「# END WordPress」にはちゃんと意味があって、プラグインの有効化時などに自動でhtaccessが書き換わるときは、この「# BEGIN WordPress」から「# END WordPress」で挟まれた部分だけが書き換わるようになっている。

ってことで、もし自分で今回の404エラーのような内容を書くのであれば、この外側に書いた方が良い。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} xmlrpc\.php$
RewriteCond %{REMOTE_HOST} !^localhost$
RewriteRule .* / [R=404,L]
</IfModule>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

例えばこんな感じですね。これなら上半分の404エラーに関する部分が上書きされて消されちゃうこともない。

あるいは「# BEGIN 〜」ってやつ自体を消しちゃっても良いのかもしれないけど、確認はしてないですが、それだと何か不具合が起こるかもしれない。だから一応残しといた方が良いんじゃないかなぁ。






もうちょい簡単な説明にするつもりでしたが、ちょっち長くなっちゃいましたね。まあいつものこと。あかつきのお宿的にはデフォなんで、許してつかあさい。

しかし、本当にこういう魔の手ってのは、どこにでも延ばしてくるんですねぇ。うちの会社のサイトなんて、まだたいしたアクセスもない弱小サイトなのに……言いたかないけど、このあかつきのお宿よりもアクセスが少ないくらいなのに……そんなことは関係ないのね。

匿名 2015年09月24日 22:48:52
私も今日見たら.htaccessファイルが書きかえられていたので焦ったのですが、# BEGIN WordPressと書かれていましたのでこの記事を見て少し安心しました。

でもローカルにあった.htaccessファイルで上書きしてしまいました・・・。

コンピュータは奥が深くて難しいです。
まっち~(管理人) 2015年09月25日 11:26:45
>匿名さん
僕も以前は書き替わるたびに、何か不正な攻撃を受けているんだろうと思って、ローカルで直したものを再度上書きしてました。

原因が分かれば何てことないんですけど、普段、勝手に書き替わることのあまりないファイルだから、何が起こったん? って思っちゃいますよね。
もしかしたら何か関連しているかも?