特権セッションの記録とアカウント管理
接続の事実と操作記録の有無を分け、監査の不足箇所を具体的に示します。
説明
中継装置を通した特権操作では、誰がどの対象へ接続し、何を実行したかを対応付けます。中継を通らない緊急接続や管理外アカウントは、同じ録画・記録の範囲に入りません。
固定の接続監査とコマンド記録を検索し、記録のある経路とない経路を調べます。最後に特権アカウント台帳を照合し、管理対象の範囲を確認します。
接続の事実と操作記録の有無を分け、監査の不足箇所を具体的に示します。
1対象と接続経路を並べる
brokerは中継経由、directは直接接続です。
from sp12 import *
from sp02 import show対象と接続経路を並べる
db=connect()
show(db,"SELECT * FROM audit ORDER BY t")aliceの2操作とemergencyのログインが同じdb7を対象にしています。
2セッション内のコマンドを開く
s7に保存された操作記録です。
showセッション内のコマンドを開く(db,"SELECT * FROM recording ORDER BY t")SELECTとUPDATEが残っています。コマンドの要求だけでは更新成功を証明しないため、結果や接続先の監査も照合します。
3要求を実行結果と照合する
一時DBの公開表へ記録のSQLを実行します。
db.execute("CREATE TABLE sample(name TEXT,flag INTEGER)")
db.execute("INSERT INTO sample VALUES ('public',0)")
show(db,"SELECT name,flag FROM sample")
db.execute("UPDATE要求を実行結果と照合する sample SET flag=1")
show(db,"SELECT name,flag FROM sample")flagが0から1へ変わりました。この試料では対象の値まで確認でき、単なる操作要求の記録より確かな更新根拠になります。
4直接接続に対応する操作記録を探す
時刻で突き合わせ、記録がない行も残します。
show(db,"SELECT a.t,a.subject,a.route,r.command FROM audit a LEFT JOIN直接接続に対応する操作記録を探す recording r USING(t) ORDER BY a.t")30秒のdirect行はcommandがNULLです。直接接続を使った事実は分かりますが、その後の操作内容はこの資料にありません。
5管理対象の特権アカウントを確認する
managedはPAM管理下かを示す教材用属性です。
show管理対象の特権アカウントを確認する(db,"SELECT * FROM account ORDER BY name")db-adminは管理下、local-maintは管理外の特権アカウントです。readerは非特権です。
6特権だが管理外のものを抽出する
privilegedとmanagedを組み合わせます。
show特権だが管理外のものを抽出する(db,"SELECT name FROM account WHERE privileged=1 AND managed=0")local-maintが出ます。管理下のセッション記録だけを調べても、このアカウントの利用を網羅したことにはなりません。
7経路ごとに操作記録の有無を集計する
ログイン数ではなく、対応するコマンドが残るかも数えます。
show(db,"SELECT a.route,COUNT経路ごとに操作記録の有無を集計する(*) AS audit_rows,COUNT(r.command) AS command_rows FROM audit a LEFT JOIN recording r USING(t) GROUP BY a.route ORDER BY a.route")brokerは2行とも対応し、directは監査1行に対してコマンド0行です。実資料では時刻だけでなく接続IDや対象IDも使って対応付けます。
まとめ
主体・接続先・経路を含めて記録を結びます。
要求コマンドと実行結果を照合します。
直接接続と管理外特権を棚卸しします。
操作履歴と解説を振り返れます。
Python 3.15 / 固定ID・認可条件・SQLite
from sp12 import *
from sp02 import show
db=connect()
show(db,"SELECT * FROM audit ORDER BY t")t | subject | target | route | operation 10 | alice | db7 | broker | SELECT 20 | alice | db7 | broker | UPDATE 30 | emergency | db7 | direct | LOGIN
show(db,"SELECT * FROM recording ORDER BY t")t | session | command 10 | s7 | SELECT name FROM sample 20 | s7 | UPDATE sample SET flag=1
db.execute("CREATE TABLE sample(name TEXT,flag INTEGER)")
db.execute("INSERT INTO sample VALUES ('public',0)")
show(db,"SELECT name,flag FROM sample")
db.execute("UPDATE sample SET flag=1")
show(db,"SELECT name,flag FROM sample")name | flag public | 0 name | flag public | 1
show(db,"SELECT a.t,a.subject,a.route,r.command FROM audit a LEFT JOIN recording r USING(t) ORDER BY a.t")t | subject | route | command 10 | alice | broker | SELECT name FROM sample 20 | alice | broker | UPDATE sample SET flag=1 30 | emergency | direct | NULL
show(db,"SELECT * FROM account ORDER BY name")name | managed | privileged db-admin | 1 | 1 local-maint | 0 | 1 reader | 0 | 0
show(db,"SELECT name FROM account WHERE privileged=1 AND managed=0")name local-maint
show(db,"SELECT a.route,COUNT(*) AS audit_rows,COUNT(r.command) AS command_rows FROM audit a LEFT JOIN recording r USING(t) GROUP BY a.route ORDER BY a.route")route | audit_rows | command_rows broker | 2 | 2 direct | 1 | 0
演習完了