はじめに

 サイバーセキュリティに携わる者なら一度くらいはKDD Cup 99 Dataなるデータセットの名を耳にしたことがあるのではないだろうか.KDD Cupは国際会議SIGKDDによるデータマイニングのコンペで,KDD Cup 99 Dataはそのためのネットワーク侵入検知にまつわるデータ.正常通信と攻撃を分類するタスクが与えられた.
 見てみよう.

データセットの構成

 データは現在,カリフォルニア大学アーバイン校によって配布されている.
 それぞれのファイル内容は下記の通り:

ファイル名 ファイル内容
kddcup.data フルデータ
kddcup.data_10_percent フルデータの10%を抽出した学習用データ
corrected 正常・攻撃のラベル付けがなされた評価用データ
kddcup.testdata.unlabeled 正常・攻撃のラベル付けがなされていないデータ
kddcup.testdata.unlabeled_10_percent 正常・攻撃のラベル付けがなされていないデータの10%サブセット
kddcup.newtestdata_10_percent_unlabeled 正常・攻撃のラベル付けがなされていないデータの10%サブセット

 ファイルの中身はこんな調子:

1
2
3
4
5
6
7
8
9
$ wget -r -l 1 http://kdd.ics.uci.edu/databases/kddcup99/
$ gunzip -r kdd.ics.uci.edu/kddcup99
$ ln -s kdd.ics.uci.edu/databases/kddcup99 kddcup99
$ head -5 kddcup99/kddcup.data
0,tcp,http,SF,215,45076,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,0,0,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,normal.
0,tcp,http,SF,162,4528,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,1,1,1.00,0.00,1.00,0.00,0.00,0.00,0.00,0.00,normal.
0,tcp,http,SF,236,1228,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,2,2,1.00,0.00,0.50,0.00,0.00,0.00,0.00,0.00,normal.
0,tcp,http,SF,233,2032,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,3,3,1.00,0.00,0.33,0.00,0.00,0.00,0.00,0.00,normal.
0,tcp,http,SF,239,486,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,3,3,0.00,0.00,0.00,0.00,1.00,0.00,0.00,4,4,1.00,0.00,0.25,0.00,0.00,0.00,0.00,0.00,normal.

 これは,ファイルの特徴をカンマ区切りで列挙したもの.列に特徴名を振れば,pandas(や,scikit-learn)での扱いも楽.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> import pandas
>>>
>>> col_names = ["duration","protocol_type","service","flag","src_bytes",
... "dst_bytes","land","wrong_fragment","urgent","hot","num_failed_logins",
... "logged_in","num_compromised","root_shell","su_attempted","num_root",
... "num_file_creations","num_shells","num_access_files","num_outbound_cmds",
... "is_host_login","is_guest_login","count","srv_count","serror_rate",
... "srv_serror_rate","rerror_rate","srv_rerror_rate","same_srv_rate",
... "diff_srv_rate","srv_diff_host_rate","dst_host_count","dst_host_srv_count",
... "dst_host_same_srv_rate","dst_host_diff_srv_rate","dst_host_same_src_port_rate",
... "dst_host_srv_diff_host_rate","dst_host_serror_rate","dst_host_srv_serror_rate",
... "dst_host_rerror_rate","dst_host_srv_rerror_rate","label"]
>>>
>>> kdd_data_10percent = pandas.read_csv("kddcup99/kddcup.data_10_percent", header=None, names = col_names)

 学習用データは通常データ,22種類の攻撃データの計23種類のデータからなる.評価用データは,学習用データに加えて17種類の攻撃データを含んでいる.これらの攻撃は4つのクラスに大別される:

クラス 説明 サブクラス
Normal 通常のコネクション normal
Probe 攻撃対象の探索・調査 ipsweep, nmap, postsweep, satan, mscan, saint
DoS DoS攻撃 back, land, neptune, pod, smurf, teardrop, mailbomb, apache2, processtable, udpstorm
U2R ローカルマシンからrootへの許可されていないアクセス buffer.overflow, localmodule, perl, rootkit, httptunnel, xterm, ps, worm
R2L リモートマシンからの許可されていないアクセス ftp_write, guess_passwd, imap, multihop, phf, spy, warezclient, warezmaster, snmpgetattack, snmpguess, xsnoop, named, sendmail, sqlattack, xlock

 サブクラス名から古臭さがにじんでいるが,データセットは近年の研究でも広く用いられているものだ.まあ単純に同規模の新しいデータセットがないからだろう.
 だいたいの論文はkddcup.data_10_percentを用いて学習し,correctedを用いて評価するという流れになっている.
 ところで,このデータセットに付随したタスクは正常通信と攻撃の二値(まあ多値分類になりはするが)分類だが,これは異常検知とどう違うのだろうか.ものの本によると,二値分類はベイズ決定則(条件付き分布$p(x|y=1)p(y=1)$$p(x|y=0)p(y=0)$の比が1を超えたら異常と判定),異常検知はネイマン・ピアソン決定則($p(x|y=1)$$p(x|y=0)$の比がある閾値を超えたら異常と判定)にもとづいている.ここで,異常検知問題ではほとんどつねに$p(y=1)<<p(y=0)$であるため,ベイズ決定則は異常判定を強く抑制する.そういうわけで,標本の割合を吟味して二値分類器の閾値をスライドさせていくことが重要となってくるらしい.

データセット形式への変換

 tcpdump2gureKDDCup99は,Bro IDSのプラグインとして,おなじみのpcapファイルをKDD Cup 99 Dataのフォーマットに変換してくれる.Bro IDSはSnortには及ばずともそこそこ由緒あるIDSで,GitHubリポジトリは米国政府公式のリポジトリリストにも掲載されている.
 まずBro IDSをインストールする.

1
2
3
4
5
6
$ sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev
$ git clone --recursive git://git.bro.org/bro
$ cd bro
$ ./configure
$ make -j4
$ sudo make install

 私はpyenvからインストールしたPython 2.7.11を常用しているのだが,Bro IDSをmakeするにはCFLAGS="-fPIC" pyenv install 2.7.11のように共有ライブラリ用のオプションをつけてPythonを再インストールする必要があった.
 さてWireshark公式が公開しているサンプルデータをKDD Cup 99 Dataの形式に変換してみる.

1
2
3
4
5
6
7
8
9
10
11
$ cd
$ git clone git@github.com:inigoperona/tcpdump2gureKDDCup99
$ gcc tcpdump2gureKDDCup99/trafAld.c -o tcpdump2gureKDDCup99/trafAld.out
$ wget "https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=zlip-1.pcap" -O zlip-1.pcap
$ bro -r zlip-1.pcap tcpdump2gureKDDCup99/darpa2gurekddcup.bro > conn.list
$ cat conn.list
1 955453631.643199 1024 53 10.0.0.1 146.84.28.88 0.000000 udp 53 S0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
$ sort -n conn.list > conn_sort.list
$ tcpdump2gureKDDCup99/trafAld.out conn_sort.list
$ cat trafAld.list
1 955453631.643199 1024 53 10.0.0.1 146.84.28.88 0.000000 udp 53 S0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0 0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

 pcapファイルをPythonで分析したければそのまま(scapyや)pandasに突っ込むだろうけど,KDD Cup 99 Dataと比較したい場合には使えるかも.

おわりに

 名前は聞くけど触ったことないなということで.やらなければならない作業が進まないとこういう現実逃避が捗る捗る.

参考文献

 はい.