ちょっと話題の記事

【実録】WordPressの怪しい挙動をlsofとstraceコマンドで調査する方法

2015.11.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹@上越妙高オフィスです。

利用しているEC2を踏み台にした外部への攻撃が行われていると、攻撃先のサーバー管理者からAWS宛に不正利用報告(Abuse)が送られる場合があります。AWSでは報告を受けて、そのサーバー(IPアドレス)の利用者宛に警告メール(Abuse Report)で通知します。

今回、とあるAbuse Reportが届いた際の攻撃手段の調査をメモしたので、主に有用だったlsofとstraceコマンドの使い方についてまとめました。

EC2マネージメントコンソールで状態を確認する

まず確認するのはマネージメントコンソールです。AWSから通知のあったIPアドレス(Elastic IP)から、EC2インスタンスを特定します。

次に各種CloudWatchのメトリクスを確認します。外部への攻撃を行われるとNetwork Outが極端に高くなる傾向があります。これにより何月何日の何時頃に攻撃が仕掛けられたのが検討をつけることができます。 またセキュリティーグループのチェックも重要です。特にssh(tcp/22)がインターネット全体(0.0.0.0/0)に公開されていると、侵入対象になる可能性が高くなるようです。

今回のサーバーについても直近2週間のNetwork Outの傾向を確認しました。しかし顕著なトラフィック上昇は見受けられませんでした。またセキュリティーグループも一部のメンテナンス用IPアドレスのみが接続許可されている状態でした。

この時点ではAbuse Reportが誤報なのではないかと半信半疑で進めています。

lsofで外部と通信を行っているプロセスを特定する

マネージメントコンソールからではこれ以上の調査は難しいため、実際にサーバーにログインして調査を進めます。

まずps -efコマンドで怪しいプロセスが起動していないか確認します。しかしLinuxの標準的なプロセスとApache httpdのみで特に怪しいプロセスは起動していませんでした。

外部へアタックを行っているということから、TCP/IPの通信をみれば分かるかも・・・ということで、通信先IPアドレスとそれを使っているプロセスを調べるためにlsofを実行しました。HTTP(tcp/80)、HTTPS(tcp/443)で通信しているものの一覧から、localhostと自身がHTTPでLISTENしているものを除外、さらにS3との通信は除外してみました。

# ※実行にはroot権限が必要です
# lsof -Pi|grep -e ':80' -e ':443'|grep -v -e 'localhost:80' -e 'ip-10-0-0-49.ap-northeast-1.compute.internal:80'|grep -v s3-ap-northeast-1|grep -v LISTEN
httpd     18552 apache    4u  IPv4 1656303825      0t0  TCP ip-10-0-0-49.ap-northeast-1.compute.internal:57498->XXX.XXX.XXX.XXX:80 (ESTABLISHED)
httpd     28456 apache    4u  IPv4 1656303016      0t0  TCP ip-10-0-0-49.ap-northeast-1.compute.internal:48215->www.example.com:80 (ESTABLISHED)

発見。

どうやらhttpdプロセスが悪さをしているようです。さらに上記コマンドをwatchコマンドに渡して5秒毎にみてみると、常に同一プロセスID(上記だと18552と28456)が怪しい通信していることが分かりました。 このhttpdにはPHPが組み込まれているので、なにかしらPHPスクリプトが実行されているのだと推測できます。しかし特定のhttpdプロセスがどのPHPスクリプトを実行しているのか調べる手段はなさそうです。

lsofコマンドに対象のプロセスIDを渡し、詳しいプロセス情報を得てみます。いろいろ情報が得られるのですが、プロセスのカレントディレクトリを注目してみました。

# lsof -p 28456 | grep cwd

httpd   28456 apache  cwd    DIR      202,1      4096     291401 /home/apache/html/wp-content/plugins

どうやらWordPressのプラグインが原因のようです。

straceコマンドでプロセスの挙動をみる

特定のhttpdプロセスがどのPHPスクリプトを実行しているのか分からないため、straceコマンドを使ってこのプロセスが呼び出しているシステムコールをみてみることにします。

straceコマンドはAmazon Linuxなら標準でインストールされています。使い方は簡単で、straceコマンドの-pオプションで対象のプロセスIDを渡せばいいだけです。

# strace -p 28456
Process 28456 attached - interrupt to quit

connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.0.2")}, 16) = 0
sendto(4, "\373\330\1\0\0\1\0\0\0\0\0\0\3www\25example\25com"..., 50, MSG_NOSIGNAL, NULL, 0) = 50
recvfrom(4, "\373\330\201\200\0\1\0\1\0\1\0\0\3www\25example\25com"..., 1968, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("10.0.0.2")}, [16]) = 137
connect(4, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("YYY.YYY.YYY.YYY")}, 16) = -1 EINPROGRESS (Operation now in progress)
sendto(4, "POST /wp/wp-login.php HTTP/1.1\r\n", 32, MSG_DONTWAIT, NULL, 0) = 32
sendto(4, "Host: www.example.com."..., 40, MSG_DONTWAIT, NULL, 0) = 40
sendto(4, "User-Agent: Mozilla/5.0 (Windows"..., 86, MSG_DONTWAIT, NULL, 0) = 86
sendto(4, "Content-Length: 52\r\n", 20, MSG_DONTWAIT, NULL, 0) = 20
sendto(4, "Accept: text/html,application/xh"..., 323, MSG_DONTWAIT, NULL, 0) = 323
sendto(4, "\r\n", 2, MSG_DONTWAIT, NULL, 0) = 2
sendto(4, "\r\n", 2, MSG_DONTWAIT, NULL, 0) = 2
sendto(4, "log=admin&pwd=555555&wp-submit=L"..., 52, MSG_DONTWAIT, NULL, 0) = 52
recvfrom(4, "HTTP/1.1 200 OK\r\nDate: Mon, 16 N"..., 8192, MSG_DONTWAIT, NULL, NULL) = 7501
recvfrom(4, "0\r\n\r\n", 8192, MSG_DONTWAIT, NULL, NULL) = 5
recvfrom(4, "", 8192, MSG_DONTWAIT, NULL, NULL) = 0
  • 4〜6行目:VPC内のDNSサーバーに対して、攻撃対象ホスト(www.example.com)の名前解決を行っています(udp/53)
  • 7行目:解決されたIPアドレス(YYY.YYY.YYY.YYY)に対してHTTP接続を行っています(tcp/80)
  • 8〜15行目:Wordpressのログインページに対してPOSTをリクエストしています。User-Agentの偽装や簡易パスワード(pwd=555555)で試行している様子が分かります。
  • 16〜18行目:レスポンスとしてHTTP 200が返ってきました。

上記を1セットにして、様々な外部サイトへ攻撃している様子がわかりました。またこの情報から次のことも分かります。

  • ファイルへのI/Oがないため、攻撃対象はファイルリストを読みこんでいるわけではない。つまりすでにメモリー内に読み込まれたリストを対象としている。
  • 攻撃開始のトリガーとなりそうなものも外部からは与えられていないため、自立型と考えられる。
  • 攻撃が成功しても、別のサーバーに情報を送っている様子はない。ファイルに保存(open)している様子もない。

このことから、httpdプロセスを再起動することで攻撃行為自体は停止できると結論付けました。実際にhttpdを再起動したところ攻撃は行われなくなりました。

その他 原因調査に利用したコマンド

今回は掲載しませんでしたが、侵入経路や変更点を確認するために下記コマンドを利用しています。

ログイン履歴調査

# last | head

Linux監査レポート

# aureport

最近(60日以内に)変更されたファイル

# find /proc/28456/cwd/ -type f -mtime -60 -ls
# find /tmp/ -type f -mtime -60 -ls
# find /var/tmp/ -type f -mtime -60 -ls

まとめ

実際の侵入経路ですが、これはまだ調査中です。おそらくWordPressプラグインの脆弱性を突かれたと考えられます。対策としては

  • 不要プラグインのアンインストール
  • WordPressおよびプラグインのバージョンアップ
  • 管理者パスワードの変更

になるかと思います。対策を実施したらAWSのAbuse Reportに対して原因と対策を返信しましょう。対策に時間がかかるようなら、サーバーを停止した上で現状を報告します。

AWSやOSレベルでセキュリティを高くしていても、ミドルウェアやフレームワークの脆弱性をついた攻撃により侵入されてしまうことがあります。外部からの攻撃を検知/防御するためにもDeepSecurity等のIDS/IPSの導入と、SoCサービスの利用をお勧めしたいと思います。

参考資料