一覧SP-12-2 · PAM:特権資格情報とセッション

特権セッションの記録とアカウント管理

接続の事実と操作記録の有無を分け、監査の不足箇所を具体的に示します。

説明

中継装置を通した特権操作では、誰がどの対象へ接続し、何を実行したかを対応付けます。中継を通らない緊急接続や管理外アカウントは、同じ録画・記録の範囲に入りません。

固定の接続監査とコマンド記録を検索し、記録のある経路とない経路を調べます。最後に特権アカウント台帳を照合し、管理対象の範囲を確認します。

接続の事実と操作記録の有無を分け、監査の不足箇所を具体的に示します。

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

1
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
2
show(db,"SELECT * FROM recording ORDER BY t")
t | session | command
10 | s7 | SELECT name FROM sample
20 | s7 | UPDATE sample SET flag=1
3
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
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")
t | subject | route | command
10 | alice | broker | SELECT name FROM sample
20 | alice | broker | UPDATE sample SET flag=1
30 | emergency | direct | NULL
5
show(db,"SELECT * FROM account ORDER BY name")
name | managed | privileged
db-admin | 1 | 1
local-maint | 0 | 1
reader | 0 | 0
6
show(db,"SELECT name FROM account WHERE privileged=1 AND managed=0")
name
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")
route | audit_rows | command_rows
broker | 2 | 2
direct | 1 | 0

演習完了