はじめに
2018年7月から1年ほどAWSの無料枠でSplunkサーバを立ててみたことがあったのですが、適当なログがなかったのでわざと22番(SSH)と8000番(SplunkGUI)をどのIPからでも受けれるように開けておいたのです。
環境はすでに無くなっているもののsecureログだけなんとなく退避してあったので、いまさらながらもう少し分析してみました。
やってみたこと
ログは2019/3/17~5/22の約60日間分で、239,804行ありました。
マシンは先日から使っているLIFEBOOK SH76/DN、Splunkは8.0.2です。
件数の推移をみる
Splunkサーバを立てた以降、乗り込んで作業することはほとんどありませんでした。なのでsecureログに何かが残るというのはそれだけで「誰かが何かしようとしている」ことに他ならぬわけでして、それなのに23万行もログがあるってどーゆーことよ、と。
時系列で件数を数えるならば「timechart」コマンドの出番。
index=xxx soucetype=linux_secure | timechart count span=1day
単純なSPLとはいえ、23万件もあるとちょっぴり時間がかかる。
・高速モード:約1.2秒
・スマートモード:約1.2秒
・詳細モード:約10秒
今はまだ23万件だからこの程度で済んでいるが、これが数百万件になったら高速モードでもそこそこ待たされる可能性がある。
まず概要を知りたいなら「tstats」コマンドがある。
| tstats count FROM index=xxx sourcetype=linux_secure BY _time, span=1day
timechartと同じ結果が、こちらのコマンドでは0.2秒で結果が得られた。仮に数百万件が対象になって件数に比例して時間がかかったとしても、元が0.2秒なら10倍でも2秒と人の許容範囲になる。
tstatsコマンドは普通のSPLと文法が違うのでいつも書き方に悩んでしまうのだが、この王道パターンだけでも記憶しておけば役に立つはず。
Search reference - tstats
https://docs.splunk.com/Documentation/Splunk/8.0.2/SearchReference/Tstats
相手のIPアドレスを抜き出してみる
何かをしようとしている「相手」の正体を暴きたいので、ログに残されたIPアドレスをざっと抜き出そうと思ったが、いくつかのパターンがあるようで、いちいち対応するのはちょっとめんどくさい。
(例)
May 22 07:51:26 ip-xxx-xxx-xxx-xxx sshd[10488]: Received disconnect from 201.39.70.186 port 56422:11: Bye Bye [preauth]
May 22 07:41:49 ip-xxx-xxx-xxx-xxx sshd[9683]: Invalid user tyler from 182.218.64.111 port 37105
May 22 07:37:43 ip-xxx-xxx-xxx-xxx sshd[9330]: Disconnected from 124.158.5.112 port 45310 [preauth]
ものによっては1回の「何か」で複数ログが出ている場合もあるが、重複して数えてもよいから、まずはIPアドレスはしっかりと取り出そうと考えてこうした。
index=xxx sourcetype=linux_secure
| rex field="_raw" "^.* (?P<ip_addr>[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}\.[1-9][0-9]{0,2}) .*"
毎回、正規表現の勉強になるのだが、前後にスペースがあって1~3桁の数字とピリオドの連続している部分をIPアドレスとして取り出せたと思う。
Search Reference - rex
https://docs.splunk.com/Documentation/Splunk/8.0.2/SearchReference/Rex
国を突き止める
SplunkにはMaxMind社という企業が提供している「グローバルIPアドレスと国、都市名」などの情報を内包している(MMDBファイルというらしい)。
この情報を使って、IPアドレスから国や都市名を変更するときに使うのが「iplocation」コマンド。
(上の続き)
| iplocation ip_addr
| where 'ip_addr'!=""
| top 20 Country
iplocationコマンドにより、Country、City、lat(緯度)、lon(経度)といったフィールドが追加される。MMDBファイルに該当するデータがあれば「Country=United States」など値が設定され、反対に該当しない場合はNULLになる(空白になる場合もあるみたいだけど、よくわかんない)
なお、上のSPLだとIPアドレスが含まれていない行が含まれているので、ip_addrが抽出できなかった行は削除した上で(where)、top 20で上位20傑を出してみた。
また、MMDBファイルはリリースする時点でSplunkのモジュールに内包されているものだが、手動で最新版に入れ替えることができる(やったことないけど)
Search reference - iplocation
https://docs.splunk.com/Documentation/Splunk/8.0.2/SearchReference/Iplocation
ここまで出来たダッシュボードはこんなところ。
折れ線グラフは1日当たりの行件数なのだが、GWのころは1日3万行を超えているときもあり、攻撃のトレンドがあることを窺い知ることができた。繰り返しになってしまうが、この期間自分はAWSサーバに乗り込んで作業はしていないのである。なのに、これなのだ。おそろしい。
地図上にポイントする
Splunkの地図は「クラスターマップ(円グラフを表示)」と「コロプレスマップ(領域を塗りつぶす)」の2つがある。せっかく国や都市の情報が得られたのだから、グラフや表じゃなくて地図で表示してみたい。
クラスターマップで表示したいときは「geostats」コマンドを使う。パラメータにはイベントに含まれるlat(緯度)とlon(経度)のフィールドを指定した上で統計(countとか)を行う。
~
| iplocation ip_addr
| where 'ip_addr'!=""
| geostats latfield=lat longfield=lon count by City
Search Reference - geostats
https://docs.splunk.com/Documentation/Splunk/8.0.2/SearchReference/Geostats
一方、コロプレスマップで表示したいときはあらかじめ統計を取った上で、国などの情報をキーとして「geom」コマンドでその領域(緯度、経度の羅列で囲んだ地図情報)に変換する必要がある。標準では「世界各国(geo_countries)」と「アメリカの各州(geo_us_states)」の2つが準備されているので今回はこれを利用するが、日本のものを表示したいときは頑張って準備が必要になる。
| iplocation ip_addr
| where 'ip_addr'!=""
| chart count limit=0 by Country
| geom geo_countries feautureIdField=Country
Search Reference - geom
https://docs.splunk.com/Documentation/Splunk/8.0.2/SearchReference/Geom
出来上がったのがコレ。
コロプレスの方が見栄えはいいが、1要素でのみの表示になる(今回の件数とか)し、ルックアップを準備するのが手間である。一方、クラスタマップは円グラフの中身を分解して表示できるので、地域別にさらにもう1つの要素(今回は都市)で区別して表示できるという違いがある。
まとめ
これだけしか可視化していないが、貴重なデータがあろうがなかろうが、グローバルにサーバを公開した場合に如何に標的とされるということはよくわかった。また、iplocationで得られたCountry=Japanのイベントは368行もあったことから、「日本だから安心」とか言ってセキュリティ設定でIPアドレス帯域を日本に絞ってもあまり意味がないことも見えた。
そんなわけで個人やプライベートでサーバ立てたらサイバー攻撃の足掛かりにされないように対策はするべきだし、企業はもっとしっかりやっていかないとこの先もっと危ないよ、と思った次第です。