【T-Pot 】Suricataログからsignatureの集計

##やりたいこと
T-Potのダッシュボード画面右下にデフォルトで表示されているsignatureを、フィルタをかけたり、表示数を増やしたりして柔軟に見てみたいので、ログから直接確認する。
![スクリーンショット 2018-11-24 2.06.46.png](https://qiita-image-store.s3.amazonaws.com/0/316440/d4876591-0d7e-a8c5-111a-39a7307b81b7.png)

##事前情報
###保存先
デフォルトでは、データの格納先は以下のパスになっている。カスタマイズされている方は読み替えてほしい。
/data/suricata/log/suricata_ews.log

###データ形式
ここには記載しないので自身で確認してほしいのだが、それぞれの行でkeyが異なっていることがわかる。
従って、何も考えずにJSON形式で読み込もうとするとエラーになる。

```shell-session
cat /data/suricata/log/suricata_ews.log | head -5
```

##signatureの表示
そのままシェルでは処理できなさそうだったので、pythonスクリプトを作ってみた。
動作を確認したバージョンは「Python 3.5.2」だったが、Python 3ならおそらく動作するだろう。
###使い方
スクリプトにkeyとなる引数を与える。
今回はsignatureを確認したいので「alert」の中の「signature」を指定する。
他のkeyを引数に与えても他の値を取得できるので色々試してみてほしい。

###sample1
```shell-session
# python3 suricata_signature.py /data/suricata/log/suricata_ews.log alert signature | sort | uniq -c | sort -rn | head -5
  39398 ET EXPLOIT [PTsecurity] DoublePulsar Backdoor installation communication
    283 ET POLICY Reserved Internal IP Traffic
    130 ET POLICY SSH session in progress on Expected Port
    100 ET WEB_SERVER SQL Errors in HTTP 200 Response (ORA-)
     84 ET WEB_SERVER SQL Errors in HTTP 200 Response (error in your SQL syntax)
```
###sample2
```shell-session
# python3 suricata_signature.py /data/suricata/log/suricata_ews.log alert signature | sort | uniq -c | sort -rn | nl | grep SQL
     4	    100 ET WEB_SERVER SQL Errors in HTTP 200 Response (ORA-)
     5	     84 ET WEB_SERVER SQL Errors in HTTP 200 Response (error in your SQL syntax)
     8	     41 ET WEB_SERVER SQL Errors in HTTP 200 Response (mysql_query)
    10	     29 ET ATTACK_RESPONSE MySQL error in HTTP response, possible SQL injection point
    14	     17 ET ATTACK_RESPONSE PostgreSQL error in HTTP response, possible SQL injection point
    18	     12 ET ATTACK_RESPONSE Oracle error in HTTP response, possible SQL injection point
    19	      6 ET ATTACK_RESPONSE DB2 error in HTTP response, possible SQL injection point
```

###コード
```python:suricata_signature.py
import json
import sys


OPTION_FLAGS = {
    "h": False,
    "k": False
}
THIS_FILE = ""
JSON_FILE = ""
ARGS = []


def parser():
    global THIS_FILE
    global JSON_FILE
    global ARGS

    argvs = sys.argv

    THIS_FILE = argvs.pop(0)
    JSON_FILE = argvs.pop(0)

    options = [option for option in argvs if option.startswith('-')]
    ARGS = [arg for arg in argvs if not arg.startswith('-')]

    for option in options:
        if option == '-h' or option == '--help':
            OPTION_FLAGS["h"] = True
        elif option == "-k":
            OPTION_FLAGS["k"] = True


def read_log(log_name):
    with open(log_name, 'r') as f:
        read_data = f.readlines()
    return read_data


def normal():
    data = read_log(JSON_FILE)

    if len(ARGS) == 0:
        for line in data:
            print(line)
    else:
        for line in data:
            try:
                json_data = json.loads(line)
                for arg in ARGS:
                    key_value = json_data[arg]
                    json_data = json.loads(json.dumps(key_value))
                print(key_value)

            except KeyError:
                pass


def check_json_keys():
    keys = set()
    data = read_log(JSON_FILE)
    for line in data:
        json_data = json.loads(line)
        keys |= set(json_data.keys())

    for key in sorted(keys):
        print(key)


def main():
    if OPTION_FLAGS["h"]:
        print("Help...is...nothing")
        exit(0)
    elif OPTION_FLAGS["k"]:
        check_json_keys()
    else:
        normal()


if __name__ == '__main__':
    parser()
    main()
```

##おまけ
オプションとして「-k」を用意した。
1階層目のkeyを一覧で出力する。
データ分析対象の確認に使用してみてほしい。

```shell_session
# python3 suricata_signature.py /data/suricata/log/suricata_ews.log -k
@timestamp
@version
alert
app_proto
dest_ip
dest_port
dns
event_type
fileinfo
flow_id
geoip
host
http
icmp_code
icmp_type
in_iface
ip_rep
path
payload_printable
proto
src_ip
src_port
ssh
stream
t-pot_hostname
t-pot_ip_ext
t-pot_ip_int
tags
timestamp
tls
tx_id
type
```

おわり