Splunkとkerasを用いた不正アクセス予測検知の仕組み（教師データ作成編）

####やりたいこと
アクセスログをもとに機械学習（ディープラーニング）で不正アクセスを予測する仕組み作る。
[1.Splunkを使い、access.logをCSVに変換](https://qiita.com/Uryy/items/8e923038b41c60cb87a5)
[<font color="Red">2.CSVファイルをもとにJupyterLab上で教師データを作る</font>](https://qiita.com/Uryy/items/2066f1377b254e46b774)　　⇦今回の内容
[3.ディープラーニングを用いて、予測精度を確かめる](https://qiita.com/Uryy/items/104a4e01d386a72dd184)

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/7bafb827-ec61-55d3-5cde-5da8ba47b29e.png">

####前回
[Splunkとkerasを用いた不正アクセス予測検知の仕組み（前処理編）](https://qiita.com/Uryy/items/8e923038b41c60cb87a5)

####環境
・JupyterLab　2.1.4  @ AWS Cloud9
・Python 3
・Splunk Enterprise　8.1  @ AWS EC2

####教師データ（答え合わせ用）作成

初期設定を行う。

```
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from distutils.util import strtobool

from sklearn.model_selection import train_test_split
from sklearn.ensemble import IsolationForest

# DataFrameで全ての行・列を表示する設定
pd.options.display.max_columns = None

```

Splunkで作成したCSVファイルを読み込む。

```
dataset_access_log = pd.read_csv('access-log_200MB.csv')
```

データを確認する。

```
dataset_access_log.head()
```
![スクリーンショット 2021-09-10 23.20.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/99e2e3f0-4986-dc58-073c-80482ccff78f.png)

```
dataset_access_log.shape
dataset_access_log.info()
```
![スクリーンショット 2021-09-10 23.23.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/5ed0e397-5a59-7086-7d3a-11d98e1fe416.png)

```
dataset_access_log.columns
```
![スクリーンショット 2021-09-10 23.24.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/19a5fae3-da94-4ed3-4720-169f3aa748f3.png)

```
dataset_access_log.isnull().sum()
```
![スクリーンショット 2021-09-10 23.26.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/7bed6ed8-c14e-a5ce-60c4-bfcfe1e0517e.png)

データのない行を削除する。

```
dataset_access_log_2 = dataset_access_log.drop(['referer_domain','referer'],axis=1).dropna()
dataset_access_log_2.isnull().sum()
```
![スクリーンショット 2021-09-10 23.32.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/3a3974b0-33ff-fa1f-e73d-db782bae15a2.png)


カラムの中から不正アクセスとして認識させる特徴量をピックアップする。
今回は暫定で以下のパラメータから抽出したが、精度についてはご愛嬌部分多目。

```
dataset_access_log_2['uri_find_%'] = dataset_access_log_2['uri'].str.find('%') + 1 #1
dataset_access_log_2['uri_find_:'] = dataset_access_log_2['uri'].str.find(':') + 1 #2
dataset_access_log_2['uri_count_:'] = dataset_access_log_2['uri'].str.count('\:') #3
dataset_access_log_2['uri_count_('] = dataset_access_log_2['uri'].str.count('\(') #4
dataset_access_log_2['uri_count_;'] = dataset_access_log_2['uri'].str.count(';') #5
dataset_access_log_2['uri_count_%'] = dataset_access_log_2['uri'].str.count('%') #6
dataset_access_log_2['uri_count_/'] = dataset_access_log_2['uri'].str.count('/') #7
dataset_access_log_2['uri_count_'] = dataset_access_log_2['uri'].str.count('\'') #8
dataset_access_log_2['uri_count_<'] = dataset_access_log_2['uri'].str.count('<') #9
dataset_access_log_2['uri_count_?'] = dataset_access_log_2['uri'].str.count('\?') #10
dataset_access_log_2['uri_count_.'] = dataset_access_log_2['uri'].str.count('.') #11
dataset_access_log_2['uri_count_#'] = dataset_access_log_2['uri'].str.count('#') #12
dataset_access_log_2['uri_count_%3d'] = dataset_access_log_2['uri'].str.count('%3d') #13
dataset_access_log_2['uri_count_%2f'] = dataset_access_log_2['uri'].str.count('%2f') #14
dataset_access_log_2['uri_count_%5c'] = dataset_access_log_2['uri'].str.count('%5c') #15
dataset_access_log_2['uri_count_%25'] = dataset_access_log_2['uri'].str.count('%25') #16
dataset_access_log_2['uri_count_%20'] = dataset_access_log_2['uri'].str.count('%20') #17
dataset_access_log_2['uri_azAZ09'] = dataset_access_log_2['uri'].str.replace('[a-zA-Z0-9_]','').str.len() #19
dataset_access_log_2['uri_count_/%'] = dataset_access_log_2['uri'].str.count('/%') #23
dataset_access_log_2['uri_count_//'] = dataset_access_log_2['uri'].str.count('//') #24
dataset_access_log_2['uri_count_./.'] = dataset_access_log_2['uri'].str.count('./.') #25
dataset_access_log_2['uri_count_..'] = dataset_access_log_2['uri'].str.count('..') #26
dataset_access_log_2['uri_count_=/'] = dataset_access_log_2['uri'].str.count('=/') #27
dataset_access_log_2['uri_count_./'] = dataset_access_log_2['uri'].str.count('./') #28
dataset_access_log_2['uri_count_/?'] = dataset_access_log_2['uri'].str.count('/?') #29
dataset_access_log_2['method_POST'] = dataset_access_log_2['method'].str.contains('POST') #18
dataset_access_log_2['method_POST_num'] = dataset_access_log_2['method_POST'].where(dataset_access_log_2['method_POST'] == 1,0) #18
dataset_access_log_2['uri_len'] = dataset_access_log_2['uri'].str.len()
dataset_access_log_2.head()
```
![スクリーンショット 2021-09-10 23.34.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/1ba3c409-484b-5c8c-0993-b710513926f0.png)

必要なカラムだけピックアップ

```
dataset_access_log_3 = dataset_access_log_2.drop(dataset_access_log_2.columns[1:8],axis=1)
dataset_access_log_3.head()
```
![スクリーンショット 2021-09-10 23.37.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/f9686c93-98bd-063d-0dbc-6476fb4368a3.png)

"method_POST"が邪魔なので削除

```
dataset_access_log_4 = dataset_access_log_3.drop(dataset_access_log_3.columns[len(dataset_access_log_3.columns) - 3 ],axis=1)
dataset_access_log_4.head()
```
![スクリーンショット 2021-09-10 23.38.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/251d1866-1fed-cef7-6023-ea015d51b03f.png)

再びデータの確認

```
dataset_access_log_4.info()
```
![スクリーンショット 2021-09-10 23.40.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/95eb5219-3020-2414-dfa8-8f62d6942cfb.png)

"method_POST_num"の型がObjectなのでintに変換

```
dataset_access_log_5 = dataset_access_log_4.astype({'method_POST_num': 'int64'})
dataset_access_log_5.info()
```
![スクリーンショット 2021-09-10 23.40.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/a2ef4730-c168-854f-17ee-fd3027978043.png)

IsolationForestを用いて異常値を抽出して教師データにする。

```
clf = IsolationForest(random_state=0).fit_predict(X)
clf
```
![スクリーンショット 2021-09-10 23.47.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/164a0f9e-a666-62db-7044-c65455c97145.png)

配列(clf)をデータフレームに追加。
負の値があるとKerasでエラーになるので0と1に変換しておく。

```
dataset_access_log_5['clf'] = clf
dataset_access_log_5.loc[dataset_access_log_5['clf'] < 0, 'clf'] = 0
dataset_access_log_5.head()
```
![スクリーンショット 2021-09-10 23.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/8082e19f-5bfb-1a77-181f-2727f3a11544.png)

csvファイルに出力。
※10文字以下のuriを見てみると、不正アクセスチックなものがほぼないので除外。

```
dataset = dataset_access_log_5[dataset_access_log_5['uri_len'] >10]
dataset.to_csv('dataset.csv')
```

以上。

[【次回】：Splunkとkerasを用いた不正アクセス予測検知の仕組み（ディープラーニング構築編）] (https://qiita.com/Uryy/items/104a4e01d386a72dd184)

####参考
[Scutum技術ブログ](https://www.scutum.jp/information/waf_tech_blog/2021/01/waf-blog-077.html)
[異常検出アルゴリズム Isolation Forest](https://data-analysis-stats.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92/%E7%95%B0%E5%B8%B8%E6%A4%9C%E5%87%BA%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0-isolation-forest/)