LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-09-11

やりたいこと

アクセスログをもとに機械学習(ディープラーニング)で不正アクセスを予測する仕組み作る。
1.Splunkを使い、access.logをCSVに変換
2.CSVファイルをもとにJupyterLab上で教師データを作る  ⇦今回の内容
3.ディープラーニングを用いて、予測精度を確かめる

前回

Splunkとkerasを用いた不正アクセス予測検知の仕組み(前処理編)

環境

・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

dataset_access_log.shape
dataset_access_log.info()

スクリーンショット 2021-09-10 23.23.38.png

dataset_access_log.columns

スクリーンショット 2021-09-10 23.24.54.png

dataset_access_log.isnull().sum()

スクリーンショット 2021-09-10 23.26.08.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

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

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

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

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

"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

再びデータの確認

dataset_access_log_4.info()

スクリーンショット 2021-09-10 23.40.10.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

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

clf = IsolationForest(random_state=0).fit_predict(X)
clf

スクリーンショット 2021-09-10 23.47.25.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

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

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

以上。

【次回】:Splunkとkerasを用いた不正アクセス予測検知の仕組み(ディープラーニング構築編)

参考

Scutum技術ブログ
異常検出アルゴリズム Isolation Forest

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0