Kerberos認証ログの分析
aliceのチケット記録と接続先ws7のログオンを時刻、アカウント、接続元で照合します。サービスチケットの発行があっても、サービス利用の裏付けがない場合を確認します。
説明
KerberosではTGTを得てからサービス向けチケットを要求します。ドメインコントローラーの4768と4769はそれぞれの要求を記録します。NTLMの4776は資格情報の検証を記録し、接続先で何をしたかまでは示しません。
aliceのチケット記録と接続先ws7のログオンを時刻、アカウント、接続元で照合します。サービスチケットの発行があっても、サービス利用の裏付けがない場合を確認します。
1ドメイン側の要求を並べる
eventとstatusで要求の種類と成否を確認します。serviceは関連資料から補った要求SPNです。4769の生のServiceNameはサービスアカウント名を示すため、同じ列と読み替えないようにします。4776には接続先の情報がなく、この列はNULLです。
from oplab import *
db=connect(2)
show(db, 'SELECTドメイン側の要求を並べる * FROM tickets ORDER BY t')4768はTGT、4769はcifs/ws7とhttp/app7のチケット要求です。4776のstatusは失敗を示しています。
2サービス向け要求を抽出する
TGTの取得とサービス向け要求を分けて表示します。
show(db, 'SELECTサービス向け要求を抽出する id,t,account,service,client FROM tickets WHERE event=4769 AND status="0x0" ORDER BY t')cifs/ws7とhttp/app7の2件です。成功した発行記録だけでは接続先への到達や利用を証明できません。
3接続先の認証方式を確認する
ws7で成功したログオンの認証パッケージを見ます。
show(db, 'SELECT接続先の認証方式を確認する id,t,account,package,src FROM auth WHERE host="ws7" AND boot="b1" AND event=4624')a2はKerberosで、接続元は192.0.2.9です。ドメイン側と接続先側の二つの観測点を照合できます。
4時間幅を限定して対応候補を探す
サービス名、主体、接続元、発行後5秒以内という条件をそろえます。時刻だけの一致を避けます。
show(db, 'SELECT時間幅を限定して対応候補を探す k.id,a.id,k.service,a.t-k.t AS seconds FROM tickets k JOIN auth a ON k.account=a.account AND k.client=a.src AND k.service="cifs/"||a.host AND a.t BETWEEN k.t AND k.t+5 WHERE k.event=4769 AND a.event=4624')k2とa2が1秒差で対応します。この条件による候補であり、一意な共通トランザクションIDによる証明とは強さが異なります。
5NTLMの失敗を読む
4776は端末側の4625と項目が異なります。clientはこの試料では端末名です。
show(db, 'SELECTNTLMの失敗を読む id,event,client,status FROM tickets WHERE event=4776')client7からのNTLM資格情報検証が失敗しています。4776の記録には接続先端末が含まれません。clientは送信元端末名なので、IPアドレスとそのまま結合せず、端末台帳などで対応を確認します。
6利用を裏付けられない発行を探す
対応する接続先の成功記録がないチケット要求を残します。
show(db, 'SELECT利用を裏付けられない発行を探す k.id,k.service FROM tickets k WHERE k.event=4769 AND NOT EXISTS (SELECT 1 FROM auth a WHERE a.event=4624 AND a.account=k.account AND a.src=k.client AND k.service="cifs/"||a.host AND a.t BETWEEN k.t AND k.t+5)')k3は発行を確認できますがapp7の利用記録がありません。追加調査はapp7側のログや収集状況へ進みます。
まとめ
k3は発行を確認できますがapp7の利用記録がありません。追加調査はapp7側のログや収集状況へ進みます。
表示された証拠IDと検索条件を残すと、調査結果を元の記録までたどれます。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite・固定の調査記録
from oplab import *
db=connect(2)
show(db, 'SELECT * FROM tickets ORDER BY t')id | t | dc | event | account | service | client | status k1 | 8 | dc1 | 4768 | CORP/alice | krbtgt | 192.0.2.9 | 0x0 n1 | 9 | dc1 | 4776 | CORP/alice | NULL | client7 | 0xC000006A k2 | 11 | dc1 | 4769 | CORP/alice | cifs/ws7 | 192.0.2.9 | 0x0 k3 | 15 | dc1 | 4769 | CORP/alice | http/app7 | 192.0.2.9 | 0x0
show(db, 'SELECT id,t,account,service,client FROM tickets WHERE event=4769 AND status="0x0" ORDER BY t')id | t | account | service | client k2 | 11 | CORP/alice | cifs/ws7 | 192.0.2.9 k3 | 15 | CORP/alice | http/app7 | 192.0.2.9
show(db, 'SELECT id,t,account,package,src FROM auth WHERE host="ws7" AND boot="b1" AND event=4624')id | t | account | package | src a2 | 12 | CORP/alice | Kerberos | 192.0.2.9
show(db, 'SELECT k.id,a.id,k.service,a.t-k.t AS seconds FROM tickets k JOIN auth a ON k.account=a.account AND k.client=a.src AND k.service="cifs/"||a.host AND a.t BETWEEN k.t AND k.t+5 WHERE k.event=4769 AND a.event=4624')id | id | service | seconds k2 | a2 | cifs/ws7 | 1
show(db, 'SELECT id,event,client,status FROM tickets WHERE event=4776')id | event | client | status n1 | 4776 | client7 | 0xC000006A
show(db, 'SELECT k.id,k.service FROM tickets k WHERE k.event=4769 AND NOT EXISTS (SELECT 1 FROM auth a WHERE a.event=4624 AND a.account=k.account AND a.src=k.client AND k.service="cifs/"||a.host AND a.t BETWEEN k.t AND k.t+5)')id | service k3 | http/app7
演習完了