SQLインジェクションの検出(エントロピー編)
ログ情報の数値化
こちらの書籍の7章にSQLインジェクションの検出方法が記載されている。
GitHub - oreilly-japan/ml-security-jp: 『セキュリティエンジニアのための機械学習』のリポジトリ
使用されているデータセットがこちらのHTTPリクエストのログ。
データの概要としては、
- 通常データ:19,304件
- 異常データ:11,763件
異常データの内訳は、
- SQLインジェクション:10,852件
- クロスサイトスクリプティング:532件
- コマンドインジェクション:89件
- パストラバーサル:290件
となっている。
ある程度、WEBアプリケーションの脆弱性に対する攻撃知識があれば、特定の文字列によって推測できるものもある。例えば、SQLインジェクションであれば、シングルクォーテーションの記号などが該当する。
書籍の中では、そのようにドメイン知識に基づいて特徴量を追加することと、単純に文字列を数値化する方法として、エントロピーを算出していた。
それ以外に、ドメイン知識に基づかない方法としてN-gramが紹介されていた。
エントロピーについて
シャノンのエントロピーを使って数値化します。公式は以下、というところでいきなり躓きます。
上記の式を分解していく。
この値は、情報量と確率(P)をかけたものの総和。
情報量は以下の公式で算出される。
確率(P)の算出方法について。
例えば、AAABCDEFGH、という8種類の文字からなる10桁の文字列があると仮定する。
1文字づつに区切って出現回数を算出すると以下になる。
A:3回
B~H:1回
これを文字数の10で割ると、文字の出現率、という確率(P)にできる。
A:0.3
B~H:0.1
情報量は、
A:1.73(-log₂0.3)
B~H:3.32(-log₂0.1)
となる。
エントロピーは、
A(0.3x1.73)+B(0.1x3.32)+C(0.1x3.32)+D(0.1x3.32)+E(0.1x3.32)+F(0.1x3.32)+G(0.1x3.32)+H(0.1x3.32)
=2.834
と計算される。
この計算を用いて、HTTPログのクエリ文字のエントロピーを算出して、文字列を数値化して、機械学習に使います。
以下がそのPythonのコード。
import numpy as np
import pandas as pd# HTTPクエリストリングのエントロピーの計算
def H_entropy(x):
prob = [ float(x.count(c)) / len(x) for c in dict.fromkeys(list(x)) ]
H = - sum([ p * np.log2(p) for p in prob ])
return H
以下のサイトでは、説明付きで別のコードが紹介されています。
実際にSQLインジェクションのデータと、通常のデータとではエントロピーの分布が異なる。
SQLインジェクションのデータの方がエントロピーが大きくなってたが、その理由がイマイチ良く分からない。
まとめ
特徴量エンジニアリングの一つとして、ログファイルの文字列からエントロピーを算出して数値化できる。