一覧OP-08-2 · 横断相関と攻撃経路の再構成

時刻のずれと欠落を考慮したタイムライン

ws8の時計が5秒進んでいた例を補正し、同時刻に見える別端末の活動や収集停止期間を確認します。確実な関係を残しつつ、順序を決められない部分を表現する方法を学びます。

説明

複数端末の時系列を再構成するときは、時計のずれと測定誤差を考慮します。補正後の時刻が近い行でも、因果関係があるとは限りません。直接の関係を示す資料と時間上の近さを分けます。

ws8の時計が5秒進んでいた例を補正し、同時刻に見える別端末の活動や収集停止期間を確認します。確実な関係を残しつつ、順序を決められない部分を表現する方法を学びます。

1端末の時計差を確認する

offsetは基準時刻に対する進み、uncertaintyは補正後の誤差幅です。単位は秒です。

from oplab import * db=connect(8) show(db, 'SELECT端末の時計差を確認する * FROM clocks ORDER BY host')

ws8は5秒進み、ws9の誤差幅は3秒です。補正値があっても完全な時刻精度が得られるわけではありません。

2補正した時刻で並べる

記録時刻から進みの分を引きます。

show(db, 'SELECT補正した時刻で並べる r.id,r.host,r.t,c.offset,r.t-c.offset AS corrected FROM records r JOIN clocks c USING(host) ORDER BY corrected,r.id')

e2とe4は補正後102ですが、同じ活動とは限りません。異なる主体の同時活動が同じ時間軸に現れています。

3誤差を含む範囲を表示する

補正時刻の前後にuncertaintyを加減します。

show(db, 'SELECT誤差を含む範囲を表示する r.id,r.t-c.offset-c.uncertainty AS earliest,r.t-c.offset+c.uncertainty AS latest FROM records r JOIN clocks c USING(host) ORDER BY earliest,r.id')

e4の範囲は99〜105秒です。近い時刻の行に厳密な前後関係を付けるには、時刻以外の根拠が必要です。

4直接結ばれた経路を確認する

記録の順番とは独立に、コピーとファイルオープンの証拠を読みます。

show(db, 'SELECT直接結ばれた経路を確認する e.source,e.target,e.evidence FROM edges e ORDER BY source')

e1→e2→e3は証拠に対応します。e4を途中に挿入する根拠はありません。

5収集停止の範囲を確認する

gapsの時刻は端末側の未補正の値です。時計表を使って同じ基準へ直します。

show(db, 'SELECT収集停止の範囲を確認する g.host,g.start-c.offset AS start_utc,g.end-c.offset AS end_utc,g.reason FROM gaps g JOIN clocks c USING(host)')

ws8のプロセス収集は基準98〜103秒が欠落しています。ファイル記録があることから、別のプロセス記録も完全だとは言えません。

6関係が未確認の活動を抽出する

証拠付きの辺を持たない行を、無理に主経路へ結ばず残します。

show(db, 'SELECT関係が未確認の活動を抽出する r.id,r.host,r.kind FROM records r WHERE NOT EXISTS (SELECT 1 FROM edges e WHERE e.source=r.id OR e.target=r.id)')

e4は他の活動との関係が未確認です。独立した活動として記録し、対応する証拠を残します。

まとめ

e4は他の活動との関係が未確認です。独立した活動として記録し、対応する証拠を残します。

表示された証拠IDと検索条件を残すと、調査結果を元の記録までたどれます。

操作履歴と解説を振り返れます。

Python 3.15 / SQLite・固定の調査記録

1
from oplab import * db=connect(8) show(db, 'SELECT * FROM clocks ORDER BY host')
host | offset | uncertainty
ws7 | 0 | 1
ws8 | 5 | 1
ws9 | 0 | 3
2
show(db, 'SELECT r.id,r.host,r.t,c.offset,r.t-c.offset AS corrected FROM records r JOIN clocks c USING(host) ORDER BY corrected,r.id')
id | host | t | offset | corrected
e1 | ws7 | 100 | 0 | 100
e2 | ws8 | 107 | 5 | 102
e4 | ws9 | 102 | 0 | 102
e3 | ws8 | 109 | 5 | 104
3
show(db, 'SELECT r.id,r.t-c.offset-c.uncertainty AS earliest,r.t-c.offset+c.uncertainty AS latest FROM records r JOIN clocks c USING(host) ORDER BY earliest,r.id')
id | earliest | latest
e1 | 99 | 101
e4 | 99 | 105
e2 | 101 | 103
e3 | 103 | 105
4
show(db, 'SELECT e.source,e.target,e.evidence FROM edges e ORDER BY source')
source | target | evidence
e1 | e2 | x1
e2 | e3 | file-open record o1
5
show(db, 'SELECT g.host,g.start-c.offset AS start_utc,g.end-c.offset AS end_utc,g.reason FROM gaps g JOIN clocks c USING(host)')
host | start_utc | end_utc | reason
ws8 | 98 | 103 | process collector stopped
6
show(db, 'SELECT r.id,r.host,r.kind FROM records r WHERE NOT EXISTS (SELECT 1 FROM edges e WHERE e.source=r.id OR e.target=r.id)')
id | host | kind
e4 | ws9 | process

演習完了