SplunkのSearchTutorialでいろいろと調べてみる（sourcetype=secure）

[SearchTutorial](https://docs.splunk.com/Documentation/Splunk/8.0.4/SearchTutorial/WelcometotheSearchTutorial)のデータを利用して、いろいろと調べてみる。

データについては[こちら](https://docs.splunk.com/Documentation/Splunk/latest/SearchTutorial/Aboutthetutorialdata)

今回はデータを`index=tutorial`に取り込んだので、自分の環境に合わせてください。

検索期間は「全時間」固定

#ログイン失敗した数を調べる
```sql:faild_password.spl
index=tutorial sourcetype=secure failed password 
| rex "(?<process>\w+)\[\d+\]: (?<msg>.*)" 
| rex field=msg "for (?<valid>invalid user )?(?<username>.*) from (?<src>\S+)" 
| eval status=mvindex(split(msg," "),0) 
| fillnull valid value="valid user" 
| stats count dc(username) values(username) as username by valid src delim="/"
| sort 0 src 
| nomv username
```

`sourcetype=secure`にログインの成否が記録されているので、調べてみた。
とりあえず`Accept`しているのは正規ユーザのみだったので、不正ログインだけに絞っている。

##結果

| valid | src | count | dc(username) | username |
|:--|:--|--:|--:|:--|
| invalid user  | 2.229.4.58 | 106 | 56 | admin/administrator/amavis/appserver/art/db/db2inst1/dba/demo/desktop/dwane/edmond/email/fpass/george/git/gitolite/guest/helpdesk/icinga/inet/info/informix/irc/itmL2user/itmadmin/itmuser/jabber/jetty/library/local/mailman/mysql/operator/oracle/perl/postgres/rdb/redmine/rightscale/robbie/sales/sapadmin/sunny/system/tavi/testing/tomcat/trac/uni/vmware/vpxuser/web001/whois/workshop/zabbix |
| valid user | 2.229.4.58 | 52 | 21 | apache/bin/daemon/doc/ftp/games/grumpy/hammer/happy/jboss/jira/mail/nagios/ncsd/news/nobody/root/sleepy/sneezy/squid/sync |
| valid user | 10.1.10.172 | 16 | 1 | myuan |
| valid user | 10.2.10.163 | 47 | 1 | nsharpe |
| valid user | 10.3.10.46 | 121 | 1 | djohnson |
| invalid user  | 12.130.60.4 | 164 | 69 | abc/admin/administrator/amanda/appserver ...　 |

##解説

- [Splunk Add-on for Unix and Linux](https://splunkbase.splunk.com/app/833/)を入れていれば、フィールドが切れていそうな気がするけど、切れていないので、`rex`で抽出
- [CEFとかLEEF](https://help.deepsecurity.trendmicro.com/event-syslog-message-formats.html)なんかは一回このように大きく切り出して、そこから抽出したほうがいいと思います。_transforms.conf_もそんな感じで設定できるし
- `valid`フィールドを作ったのは、最初は不正アクセスだけ表示させるため。
`stats by`の引数にしてやれば、それだけの表示できるので。
- 後々`fillnull`で無い時の値を入れてみた。
- `rex`でフィールドを抽出しなくてもいい、`mvindex(split())`はかなり使えると思います。
- `stats`のオプションの`delim=`は後の`nomv`の時用

#アカウント名の数を調べる
```sql:account_count.spl
index=tutorial sourcetype=secure failed password 
| rex "(?<process>\w+)\[\d+\]: (?<msg>.*)" 
| rex field=msg "for (?<valid>invalid user )?(?<username>.*) from (?<src>\S+)" 
| eval status=mvindex(split(msg," "),0) 
| fillnull valid value="valid user" 
| stats count dc(src) by username valid
| sort 0 - count
```

フィールド抽出を生かして、人気のあるアカウントを調べてみた。

##結果
| username | valid | count | dc(src) |
|:--|:--|--:|--:|
| root | valid user | 1493 | 182 |
| administrator | invalid user  | 1020 | 180 |
| admin | invalid user  | 938 | 177 |
| operator | invalid user  | 923 | 181 |
| mail | valid user | 753 | 176 |
| mailman | invalid user  | 752 | 175 |
| irc | invalid user  | 644 | 173 |

見事に特権ユーザっぽいアカウントの数が多い

_invalid user_は放っておいていいとして、_valid_なユーザはパスワード以外のセキュリティも検討しないといけないでしょう

#SSHのログイン時間を調べる

```sql:login.spl
index="tutorial" sourcetype=secure pam_unix sshd
| reverse
| rex "session (?<status>\w+) for user (?<username>\w+)"
| table _time status username
| streamstats count(eval(status="closed")) as session current=f by username
| stats min(_time) as firsttime max(_time) as endtime range(_time) as duration by session username
| sort 0 session
| eval duration=tostring(duration,"duration")
| convert ctime(firsttime) ctime(endtime)
```

##結果
| session | username | firsttime | endtime | duration |
|--:|:--|:--|:--|:--|
| 0 | djohnson | 05/15/2020 00:15:02 | 05/15/2020 00:15:02 | 00:00:00 |
| 0 | myuan | 05/15/2020 00:15:02 | 05/15/2020 00:15:03 | 00:00:01 |
| 0 | nsharpe | 05/15/2020 00:15:02 | 05/15/2020 00:15:02 | 00:00:00 |
| 1 | djohnson | 05/15/2020 00:15:02 | 05/15/2020 00:15:02 | 00:00:00 |
| 1 | myuan | 05/15/2020 00:15:03 | 05/15/2020 00:15:05 | 00:00:02 |
| 1 | nsharpe | 05/15/2020 00:15:02 | 05/15/2020 00:15:03 | 00:00:01 |
| 2 | djohnson | 05/15/2020 00:15:02 | 05/15/2020 00:15:02 | 00:00:00 |
| 2 | myuan | 05/15/2020 00:15:06 | 05/16/2020 00:15:02 | 23:59:56 |

なんか思ってたのと違う。
[eventgen](https://splunkbase.splunk.com/app/1924/)あたりで作ってるのかな、やっぱり

##解説

- `reverse`してからの`streamstats`でのセッション作りは定番。
- 一塊にしたい状況を`current=f`で数えてあげるとちょうどいい。
- `convert`によるepoch時間の変換は、`eval`と違って列挙できるのがありがたい。なお、表示のしかたを変えるのは`timeformat=`

#まとめ
`sourcetype=secure`だと、

- 不正ログインしたIPアドレスの数は？
- その際使用したアカウントの種類は？
- その中で正規のアカウントと思われる数は？

と言った[BOTSv1](https://github.com/splunk/botsv1)でも出てきたことを練習するにはいいと思いました。

`_time`がもっとしっかりしていれば、`timechart`で凝ったことしようと思いましたが、次で頑張ろうと思います。