一覧OP-12-2 · 探索・収集・持ち出し・影響の痕跡

データ送信の目的と成否の調査

800バイトの外向き送信と800000バイトのバックアップを調べます。失敗した試行を転送成功へ加算せず、量の大小と不審さを別々に評価する方法を学びます。

説明

大きな転送量は調査の手掛かりですが、バックアップなどの正常処理でも発生します。方向、成功・失敗、業務ジョブ、通常時の量をそろえて比較する必要があります。

800バイトの外向き送信と800000バイトのバックアップを調べます。失敗した試行を転送成功へ加算せず、量の大小と不審さを別々に評価する方法を学びます。

1送信記録を比較する

bytesはこの資料で記録された要求側の転送量です。resultが転送完了の判定です。

from oplab import * db=connect(12) show(db, 'SELECT送信記録を比較する * FROM transfer ORDER BY t')

最大はbackup7の転送です。ws7には同じ800バイトの成功と失敗が一つずつあります。

2成否ごとの量を計算する

失敗行を含めた総和と成功分を分けます。

show(db, 'SELECT成否ごとの量を計算する host,result,SUM(bytes) AS bytes FROM transfer GROUP BY host,result ORDER BY host,result')

ws7の成功は800バイトです。失敗の800をそのまま加えて1600バイトの持出し成功と報告することはできません。

3業務ジョブの通常範囲を照合する

ジョブ名を台帳へ結び、通常量の幅を表示します。

show(db, 'SELECT業務ジョブの通常範囲を照合する t.id,t.bytes,b.min_bytes,b.max_bytes,b.owner FROM transfer t JOIN baseline b USING(job)')

t2の800000は700000〜900000の範囲です。通常範囲内という理由だけで、送信先や内容の確認を省くこともできません。

4業務との対応がない送信を絞る

台帳のない転送のうち、成功記録を抽出します。

show(db, 'SELECT業務との対応がない送信を絞る t.id,t.host,t.destination,t.bytes FROM transfer t LEFT JOIN baseline b USING(job) WHERE b.job IS NULL AND t.result="success"')

t1が追加調査対象です。対応する業務記録がないことと、悪意が確定していることは異なります。

5送信元プロセスの先行活動を見る

転送元と同じプロセスの記録を検索します。

show(db, 'SELECT送信元プロセスの先行活動を見る a.id,a.action,a.target,a.result FROM activity a WHERE a.process=(SELECT process FROM transfer WHERE id="t1") ORDER BY a.t')

直前に読取りとアーカイブ作成が観測されています。持出しの可能性を調べる理由になりますが、内容の同一性は未確認です。

6観測した成功量を宛先別に残す

送信量の集計条件を明示して結果を残します。

show(db, 'SELECT観測した成功量を宛先別に残す destination,SUM(bytes) AS successful_bytes,COUNT(*) AS transfers FROM transfer WHERE result="success" GROUP BY destination ORDER BY destination')

外部保存先800、バックアップ先800000です。どちらも集計条件付きの観測量であり、意図や漏えいしたファイル数を直接表す数値ではありません。

まとめ

外部保存先800、バックアップ先800000です。どちらも集計条件付きの観測量であり、意図や漏えいしたファイル数を直接表す数値ではありません。

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

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

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

1
from oplab import * db=connect(12) show(db, 'SELECT * FROM transfer ORDER BY t')
id | t | host | process | destination | bytes | result | job
t1 | 20 | ws7 | g7 | external-store | 800 | success | NULL
t2 | 21 | backup7 | g8 | backup-store | 800000 | success | nightly
t3 | 22 | ws7 | g7 | external-store | 800 | failed | NULL
2
show(db, 'SELECT host,result,SUM(bytes) AS bytes FROM transfer GROUP BY host,result ORDER BY host,result')
host | result | bytes
backup7 | success | 800000
ws7 | failed | 800
ws7 | success | 800
3
show(db, 'SELECT t.id,t.bytes,b.min_bytes,b.max_bytes,b.owner FROM transfer t JOIN baseline b USING(job)')
id | bytes | min_bytes | max_bytes | owner
t2 | 800000 | 700000 | 900000 | backup-team
4
show(db, 'SELECT t.id,t.host,t.destination,t.bytes FROM transfer t LEFT JOIN baseline b USING(job) WHERE b.job IS NULL AND t.result="success"')
id | host | destination | bytes
t1 | ws7 | external-store | 800
5
show(db, 'SELECT a.id,a.action,a.target,a.result FROM activity a WHERE a.process=(SELECT process FROM transfer WHERE id="t1") ORDER BY a.t')
id | action | target | result
e1 | list | C:/Data | success
e2 | read | C:/Data/a.csv | success
e3 | read | C:/Data/b.csv | denied
e4 | archive | C:/Temp/data.zip | success
6
show(db, 'SELECT destination,SUM(bytes) AS successful_bytes,COUNT(*) AS transfers FROM transfer WHERE result="success" GROUP BY destination ORDER BY destination')
destination | successful_bytes | transfers
backup-store | 800000 | 1
external-store | 800 | 1

演習完了