権限変更とトークンの失効
検知の根拠となる操作列と、対応後に残るアクセス条件を確認します。
説明
権限の変更や新しい資源へのアクセスは、認証後にも起こります。現在の権限台帳、発行済みトークン、実際のアクセス記録は更新時点が異なります。
同じ主体の時系列を調べ、基準期間にない操作を抽出します。その後、権限の削除と発行済みトークンの失効を別々に試します。
検知の根拠となる操作列と、対応後に残るアクセス条件を確認します。
1同じ主体の操作を並べる
時刻は固定の開始点からの秒です。
from sp13 import *
from sp02 import show同じ主体の操作を並べる
db=connect()
show(db,"SELECT * FROM event WHERE subject='corp:u7' ORDER BY t")ログイン、report読取り、グループ変更、secret読取りが順に並びます。時刻が近いことだけで原因を確定せず、対象と権限も調べます。
2基準期間にない対象を抽出する
100秒より前に同じ主体がアクセスした対象と比較します。
show(db,"SELECT e.id,e.action,e.target FROM event e WHERE e.t>=100 AND NOT EXISTS基準期間にない対象を抽出する(SELECT 1 FROM event b WHERE b.subject=e.subject AND b.t<100 AND b.target=e.target) ORDER BY e.t")group:opsとsecret:releaseが出ます。基準期間が短いため、正当な初回利用も候補になります。
3権限変更と後続操作の時間差を求める
変更後30秒以内の同じ主体の読取りを検索します。
show(db,"SELECT a.id,b.id,b.t-a.t AS seconds FROM event a JOIN event b USING(subject) WHERE a.action='add_member' AND b.action='read' AND b.t-a.t BETWEEN権限変更と後続操作の時間差を求める 0 AND 30")e3とe4が10秒差で該当します。権限グラフや監査の変更対象を追加して、行動のつながりを検討する候補です。
4現在の権限と発行済みトークンを開く
トークン行は固定の検証済みクレームの保存資料です。
show現在の権限と発行済みトークンを開く(db,"SELECT * FROM entitlement")
show(db,"SELECT * FROM token")台帳もトークンもreaderです。発行時点の情報がどこに保存されているかを確認します。
5権限台帳だけを削除する
現在権限をなくしてから、期限内のトークンを検索します。
db.execute("DELETE FROM entitlement WHERE subject='corp:u7'")
show権限台帳だけを削除する(db,"SELECT id,role FROM token WHERE expires>150 AND revoked=0")t7は残ります。発行済みの権限を期限まで採用する設計では、台帳削除だけで即時失効しない場合があります。
6現在の台帳を参照する評価と比較する
同じ主体に現在の権限がある場合だけを抽出します。
show(db,"SELECT t.id FROM token t JOIN entitlement現在の台帳を参照する評価と比較する e ON e.subject=t.subject AND e.role=t.role WHERE t.expires>150 AND t.revoked=0")該当なしです。オンラインで現在権限を評価する方式と、発行時点のクレームだけを使う方式では結果が変わります。
7トークン失効を記録して再確認する
t7の失効状態を更新します。
db.execute("UPDATE token SET revoked=1 WHERE id='t7'")
showトークン失効を記録して再確認する(db,"SELECT id FROM token WHERE expires>150 AND revoked=0")
show(db,"SELECT id,revoked FROM token")利用可能な検索結果は空で、失効記録は1です。実システムではアプリがその失効情報を参照する経路まで確かめます。
まとめ
基準との差は調査候補として扱います。
権限削除とトークン失効を分けて確認します。
アプリが何を参照して許可するかを調べます。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite / 固定の主体・権限・操作記録
from sp13 import *
from sp02 import show
db=connect()
show(db,"SELECT * FROM event WHERE subject='corp:u7' ORDER BY t")id | t | subject | action | target e1 | 0 | corp:u7 | login | portal e2 | 60 | corp:u7 | read | report e3 | 120 | corp:u7 | add_member | group:ops e4 | 130 | corp:u7 | read | secret:release
show(db,"SELECT e.id,e.action,e.target FROM event e WHERE e.t>=100 AND NOT EXISTS(SELECT 1 FROM event b WHERE b.subject=e.subject AND b.t<100 AND b.target=e.target) ORDER BY e.t")id | action | target e3 | add_member | group:ops e4 | read | secret:release
show(db,"SELECT a.id,b.id,b.t-a.t AS seconds FROM event a JOIN event b USING(subject) WHERE a.action='add_member' AND b.action='read' AND b.t-a.t BETWEEN 0 AND 30")id | id | seconds e3 | e4 | 10
show(db,"SELECT * FROM entitlement")
show(db,"SELECT * FROM token")subject | role | version corp:u7 | reader | 1 id | subject | role | issued | expires | revoked t7 | corp:u7 | reader | 100 | 200 | 0
db.execute("DELETE FROM entitlement WHERE subject='corp:u7'")
show(db,"SELECT id,role FROM token WHERE expires>150 AND revoked=0")id | role t7 | reader
show(db,"SELECT t.id FROM token t JOIN entitlement e ON e.subject=t.subject AND e.role=t.role WHERE t.expires>150 AND t.revoked=0")id
db.execute("UPDATE token SET revoked=1 WHERE id='t7'")
show(db,"SELECT id FROM token WHERE expires>150 AND revoked=0")
show(db,"SELECT id,revoked FROM token")id id | revoked t7 | 1
演習完了