IDS・IPSの通知条件と通信制御
パケット、解析したHTTP、通知、配送の証拠をそれぞれ照合します。
説明
通知件数は、条件への一致回数や破棄したパケット数と同じとは限りません。通知を抑制する設定、ルールのaction、実行モードを分けて確認する必要があります。
同じpcapをalert・drop・rejectと通知閾値付きルールで解析した結果を読みます。オフライン解析の結果から確認できることと、配送先での観測が必要なことを整理します。
パケット、解析したHTTP、通知、配送の証拠をそれぞれ照合します。
1比較するルールを表示する
URI条件は同じで、先頭のactionだけが異なります。
from sp04 import *
for name in ('alert','drop','reject'): print((ROOT比較するルールを表示する/(name+'.rules')).read_text(),end='')alertは通知、dropはIPSでの破棄、rejectは拒否応答を伴う措置を指定します。実際の効果には実行モードと経路が関わります。
2alertの通知結果を確認する
読み込んだpcapはすべて同じです。
print(alertsalertの通知結果を確認する('split-alert'))actionはallowedです。検知したことと通信を止めたことを同一に扱いません。
3dropをオフライン解析で評価した結果を見る
この実行はpcapの読込みです。
print(alertsdropをオフライン解析で評価した結果を見る('split-drop'))この条件ではallowedと出ています。dropという規則の文字だけで、実通信の配送を阻止したとは判断できません。
4rejectの結果と観測範囲を確認する
同じpcapにrejectを指定した出力です。
print(alertsrejectの結果と観測範囲を確認する('split-reject'))
print(http('split-reject'))actionはblockedですが、読み込んだファイル内のHTTP記録は残ります。オフラインのblocked表示は、端末に拒否応答が届いた証拠ではありません。
52回一致して通知する規則を開く
閾値は送信元ごと、60秒で2回です。
print((ROOT/'threshold.rules').read_text(),end='')
print(alerts2回一致して通知する規則を開く('split-threshold'))1回だけの試料では通知が出ません。これはthreshold type thresholdの条件です。遮断actionの実行回数をこの通知件数から数えることはできません。
6通知がなくてもHTTP解析が残ることを確認する
閾値付きルールのHTTP記録を調べます。
print(http通知がなくてもHTTP解析が残ることを確認する('split-threshold'))
print([x['event_type'] for x in RESULTS['split-threshold']])/lessonは解析されています。通知抑制を、通信を観測できなかったことと取り違えないようにします。
7配送の確認に必要な項目を洗い出す
今回のEVE記録に含まれる種類をまとめます。
print(sorted配送の確認に必要な項目を洗い出す({x['event_type'] for v in RESULTS.values() for x in v}))alert、flow、httpの解析記録です。実経路での阻止を確かめるときは、送信側の結果、経路上のパケット、受信側への到達も同じ通信で照合します。
まとめ
通知閾値と通信への措置を別々に確認します。
ルールのactionと実行モードを照合します。
阻止の成否は配送先の観測も使って判断します。
操作履歴と解説を振り返れます。
Suricata 7.0.10のpcap解析結果 / Python 3.15
from sp04 import *
for name in ('alert','drop','reject'): print((ROOT/(name+'.rules')).read_text(),end='')alert http any any -> any any (msg:"Lbox lesson URI"; flow:established,to_server; http.uri; content:"/lesson"; sid:1000001; rev:1;) drop http any any -> any any (msg:"Lbox lesson URI"; flow:established,to_server; http.uri; content:"/lesson"; sid:1000001; rev:1;) reject http any any -> any any (msg:"Lbox lesson URI"; flow:established,to_server; http.uri; content:"/lesson"; sid:1000001; rev:1;)
print(alerts('split-alert'))[(1000001, 'allowed')]
print(alerts('split-drop'))[(1000001, 'allowed')]
print(alerts('split-reject'))
print(http('split-reject'))[(1000001, 'blocked')]
[('GET', 'demo.example.test', '/lesson')]print((ROOT/'threshold.rules').read_text(),end='')
print(alerts('split-threshold'))alert http any any -> any any (msg:"Lbox lesson URI"; flow:established,to_server; http.uri; content:"/lesson"; threshold:type threshold, track by_src, count 2, seconds 60; sid:1000001; rev:1;) []
print(http('split-threshold'))
print([x['event_type'] for x in RESULTS['split-threshold']])[('GET', 'demo.example.test', '/lesson')]
['http', 'flow']print(sorted({x['event_type'] for v in RESULTS.values() for x in v}))['alert', 'flow', 'http']
演習完了