囮ファイルによる検知と通知
囮への接触から通知までを識別子でたどり、根拠のない操作や人物像を補わずに説明します。
説明
デセプションでは、通常業務で使わない囮の資源や識別用トークンへの接触を観測します。接触の種類と通知の届き方を分けて調べると、単なる一覧表示とファイル読取りを取り違えずに追跡できます。
固定の囮台帳、接触記録、通知記録をSQLで結びます。通知URLに含めるトークンを解析し、通知元アドレスから分かる範囲も確認します。
囮への接触から通知までを識別子でたどり、根拠のない操作や人物像を補わずに説明します。
1囮の場所と種類を確認する
d7はファイル、d8はサービスです。
from sp21 import *
from sp02 import show囮の場所と種類を確認する
db=connect()
show(db,"SELECT * FROM decoy ORDER BY id")場所と種類が異なるため、同じ接触イベントとして一括りにしません。
2接触の種類を時系列で読む
listed、opened、callback、connectedを並べます。
show接触の種類を時系列で読む(db,"SELECT * FROM event ORDER BY t")d7は一覧表示後に開かれ、その後トークンへのcallbackがあります。d8への接続はscanner7からです。
3ファイルを開いた記録へ対象を結ぶ
targetが囮IDに対応する行を取得します。
show(db,"SELECT e.id,e.source,d.location,e.kind FROM event e JOINファイルを開いた記録へ対象を結ぶ decoy d ON e.target=d.id WHERE e.kind='opened'")e2はshare-aのd7です。listedだけで中身を読んだと判断せず、openedの根拠を使います。
4トークンを持つ通知URLを解析する
公開の固定トークンをURLのパラメーターへ入れます。
url='https://notify.example.test/event?'+urlencode({'token':'public-token-7'})
print(url)
print(parse_qsトークンを持つ通知URLを解析する(urlsplit(url).query))tokenが取り出せます。この値は囮を特定するもので、閲覧者の本人認証を行う資格情報ではありません。
5callbackを囮へ対応付ける
囮IDではなくtokenで結合します。
show(db,"SELECT e.id,e.source,d.id AS decoy,d.location FROM event e JOIN decoy d ON e.target=d.tokencallbackを囮へ対応付ける WHERE e.kind='callback'")e3はd7に対応します。sourceはproxy7なので、実際に閲覧した端末や人物をこの値だけで確定できません。
6通知の待機と配送完了を分ける
接触記録と配送台帳を結びます。
show(db,"SELECT e.id,e.kind,n.queued,n.delivered FROM event e LEFT JOIN通知の待機と配送完了を分ける notification n ON n.event=e.id ORDER BY e.t")e2はqueued=1でもdelivered=0です。接触を検知したことと、担当者へ通知が届いたことは別の状態です。
7未配送の通知を抽出する
配送の再確認が必要な行です。
show未配送の通知を抽出する(db,"SELECT event FROM notification WHERE queued=1 AND delivered=0")e2が出ます。通知が届かなかった原因は転送先やキューなど追加資料で調べ、接触自体がなかったことにはしません。
まとめ
接触の種類と対象を対応付けます。
トークンと通知元から分かる範囲を確認します。
検知と通知配送の完了を分けます。
操作履歴と解説を振り返れます。
Python 3.15 / 固定パケット・SQLiteの接続資料
from sp21 import *
from sp02 import show
db=connect()
show(db,"SELECT * FROM decoy ORDER BY id")id | location | kind | token d7 | share-a | file | public-token-7 d8 | segment-b | service | public-token-8
show(db,"SELECT * FROM event ORDER BY t")id | t | source | target | kind e1 | 10 | 192.0.2.7 | d7 | listed e2 | 20 | 192.0.2.7 | d7 | opened e3 | 21 | proxy7 | public-token-7 | callback e4 | 30 | scanner7 | d8 | connected
show(db,"SELECT e.id,e.source,d.location,e.kind FROM event e JOIN decoy d ON e.target=d.id WHERE e.kind='opened'")id | source | location | kind e2 | 192.0.2.7 | share-a | opened
url='https://notify.example.test/event?'+urlencode({'token':'public-token-7'})
print(url)
print(parse_qs(urlsplit(url).query))https://notify.example.test/event?token=public-token-7
{'token': ['public-token-7']}show(db,"SELECT e.id,e.source,d.id AS decoy,d.location FROM event e JOIN decoy d ON e.target=d.token WHERE e.kind='callback'")id | source | decoy | location e3 | proxy7 | d7 | share-a
show(db,"SELECT e.id,e.kind,n.queued,n.delivered FROM event e LEFT JOIN notification n ON n.event=e.id ORDER BY e.t")id | kind | queued | delivered e1 | listed | NULL | NULL e2 | opened | 1 | 0 e3 | callback | 1 | 1 e4 | connected | 1 | 1
show(db,"SELECT event FROM notification WHERE queued=1 AND delivered=0")event e2
演習完了