2016/03/28 17:52:11

「WordPressのxmlrpc.phpに注意」結果的にDDos攻撃受けサーバを何度も落とされた


Warning: Attempt to read property "post_excerpt" on null in /home/kpkyvkzp/public_html/unskilled.site/wp-content/themes/unskilled2/content-header-eyecatch.php on line 5
目次(クリックするとジャンプします)
  • 1:MySQLが落ちとる
  • 2:サーバ落とされた経緯
  • 2.1:気づく
  • 2.2:log確認
  • 2.2.1:secureログ
  • 2.2.2:massegesログ
  • 2.2.3:httpdログ
  • 2.2.4:wordpressのxmlrpc.php
  • 3:対策
  • 4:iptablesでhashlimitを使ってipごと弾く
  • 5:まとめ

MySQLが落ちとる

運営しているサイトの作業で、データベースを確認しようと思いAdminerで接続しようとしたところ、繋がらず。

なんかmysqldが落ちていた。

なんだこれと思い調べてみました。

結果からお伝えすると、

  • 「WordPressのxmlrpc.phpを利用したDDos攻撃による大量アクセス」

が原因でした。

以下はその時の経緯とかです。 ちなみにレンタルサーバー借りてから初めての障害。泣きそうでふた。

サーバ落とされた経緯

気づく

さっきも書いたとおり、データベースに繋がらないのが気がついた契機です。

とりあえずリソースを確認してみることに。

レンタルサーバ屋が提供しているリソースグラフをみてみるとピョコンと高くなっている部分がある。

スパイクぅぅ。

この時は日に200pvくらいのサイトしか置いてないので、こんなに負荷が高くなることはない。もちろんcronで重い処理を回してたということでもないです。

log確認

こんな時は落ち着くのが一番。まずログをみてみようということで確認。

secureログ

Dec 1 03:51:03 host-hoge sshd[9925]: fatal: Read from socket failed: Connection reset by peer

当該時間に重なるようなログは無かった。port22から進入を試みようとするログはいっぱいあったけど。

massegesログ

リソースグラフのスパイクと重なる時間にhttpdに何らかの不具合が起こったようです。

具体的にはメモリ不足が起きたらしい。そのためOOMKIllerが発動したみたいです。

Dec 1 05:08:41 host-hoge kernel: Out of memory: Kill process 5021 (httpd) score 12 or sacrifice child

OOMKillerとは、なんらかの理由でメモリが足りなくなると予め優先順位付けされたプロセスをkillしてメモリを確保しようとするLinuxの機構DEATH。

初期設定だと、データベースなんかも優先順位が高い方(殺される順番として)でWordPressなどCMSでサイトを構成している際は、httpサーバーに大量アクセスがあると必然的にデータベースが使うメモリも増大してしまうため、殺されたようです(亡)。

httpdログ

リソースグラフのスパイクと重なる時間に大量のアクセスが

46.166.139.20 - - [01/Dec/2015:07:35:54 +0900] "POST /xmlrpc.php HTTP/1.0" 500 263 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

これは抜粋したものだけど、46.166.139.20のばかやろうが秒間100以上のアクセスをしてきていました。

アクセス先はxmlrpc.php

wordpressのxmlrpc.php

最初にも述べたとおりxmlrpc.phpはWordPressのファイルです。

WordPressにはpinback機能がありますが、これはML-RPC APIを使用して実装されています。つまりxmlrpc.phpAPIです。

xmlrpc.phpPOSTリクエストを送信すると、任意のサイトにpinbackを送ることができます。

なのでこの仕組みをつかってWordPressを踏み台にDDos攻撃が可能になります。

今回は踏み台にされたようです。サーバを乗っ取られなくても攻撃の片棒を担がされたことに…。

正直に言いますとxmlrpc.phpなど知りませんでした。えへへ。

今度はWordPressが踏み台に、Pingback機能を悪用しDDoS攻撃

@MINOの現状では使うことはないですが、これデフォルトで有効になっているようです。

なんてことだ。

対策

xmlrpc.phpを削除する手もありますが、WordPressのバージョンアップ時にファイルが復活してしまうので、毎回消すのはあまりいい手ではありません。

簡単な方法としては.htaccessに以下の様に記述し、ファイル単位でアクセスを弾く手があります。

<Files xmlrpc.php>
 Order allow,deny
 Deny from all
</Files>

しかし.htaccessではアクセスを受けてから弾くため、アクセス負荷は対策が難しいのが難点です。

対策の方法はいろいろあるかと思いますが、おそらくiptablesで弾くのが良いのではないかと思います。

具体的にはhashlimitを使うのが良さそうです。

iptablesでhashlimitを使ってipごと弾く

hashlimitはipとポートを1つのグループとして監視してくれます。

イメージとしてはip単位のアクセスをカウントして、設定した条件に抵触した場合にそのipからのアクセスを遮断するという方法です。

以下hashlimitを用いた場合の設定例(一部抜粋)です。

iptables -N HTTP_DOS # "HTTP_DOS" という名前でチェーンを作る
iptables -A HTTP_DOS -p tcp -m multiport --dports 80 \
         -m hashlimit \
         --hashlimit 1/s \
         --hashlimit-burst 100 \
         --hashlimit-htable-expire 300000 \
         --hashlimit-mode srcip \
         --hashlimit-name t_HTTP_DOS \
         -j RETURN

# 解説
# -m hashlimit                       limitではなくhashlimit を利用する
# --hashlimit 3/s                    秒間3接続を上限とする
# --hashlimit-burst 5               上限を5回連続超えると制限
# --hashlimit-htable-expire 300000   管理テーブル中のレコードの有効時間(ms単位、例では30秒有効)
# --hashlimit-mode srcip             送信元アドレスでリクエスト数を管理する
# --hashlimit-name t_HTTP_DOS        /proc/net/ipt_hashlimit に保存されるハッシュテーブル名
# -j RETURN                          制限にかからなければ、親チェーンに戻る

# 制限を超えた接続の破棄とロギング
iptables -A HTTP_DOS -j LOG --log-prefix "http_dos_attack: "
iptables -A HTTP_DOS -j DROP

# HTTPへのパケットは "HTTP_DOS" チェーンへジャンプ
iptables -A INPUT -p tcp -m multiport --dports 80 P -j HTTP_DOS

iptablesであればアクセス自体を遮断できるので、負荷に対しても一定の有効性があります。

DDos攻撃の場合、僅かな時間に極端なアクセスが来るのが特徴です。そのためある程度の設定のチューニングは必要かと思いますが、通常使用時の自然なアクセス自体は排除される恐れはほとんどありません。

自然な使用で秒間100アクセスなんかならないですよね。なのでもしxmlrpc.phpを使っていた場合でも、アクセス制限を併用できます。

まとめ

  • WordPressのxmlrpc.phpは攻撃対象になる
  • iptablesのhashlimitでアクセス制限をするのがおすすめ