UACと整合性レベル
同じ利用者の通常・昇格トークンから、管理者の許可・特権・書込み制約を分けて判断します。
説明
Windowsの管理者アカウントでも、通常のアプリが常に管理者のすべての権限で動くわけではありません。UACの構成では、制限された通常トークンと昇格したトークンを使い分けます。さらにDACL、SIDの有効属性、特権、整合性レベルはそれぞれ異なる判定材料です。
LAB\ayaの二つのトークンを整理したCSVを読み、同じ利用者でもAdministrators SIDの属性が変わることを確認します。次にMediumとHighの数値、NoWriteUp、特権の有効状態を比較し、昇格しても通らない条件を確かめます。
1同じ利用者の二つのトークン
tokens.csvは通常のPowerShellと、UACで昇格したPowerShellのトークンから必要な項目を整理した教材表です。Nameが場面、AdminAttributesがAdministrators SIDの属性ビット、Integrityが整合性レベルの値です。
$tokens = Import-Csv表を読み込む .\tokens.csv二つのトークンの記録; $tokens | Format-Table Name,User,AdminAttributes,Integrity比較する列を表示両方とも利用者はLAB\ayaですが、属性と整合性レベルが違います。管理者グループに所属することと、いま使っているトークンで管理者の許可が有効なことを分けて確認します。
2利用者名が同じかを照合
通常と昇格後の行を変数に分け、Userを比較します。
$normal = $tokens | Where-Object Name -eq normal通常の行; $elevated = $tokens | Where-Object Name -eq elevated昇格後の行; $normal.User -eq $elevated.User同じ利用者か利用者が同じでも、プロセスが使うトークンは同じ状態とは限りません。UACの管理者承認モードでは、管理者の通常作業に制限されたトークンを使い、必要な操作を昇格したトークンで行います。
3Administrators SIDが許可に使われるか
SE_GROUP_ENABLEDは0x4です。CSVの文字列を整数へ変換し、ビットが立っているかを検査します。
[bool]([int]$normal.AdminAttributes -band 4)通常側の有効ビット; [bool]([int]$elevated.AdminAttributes -band 4)昇格側の有効ビット通常側の16=0x10はdeny-onlyで、Administratorsに対する許可ACEを採用する根拠になりません。拒否ACEには使われます。昇格側の7は0x4を含むため、許可判定で有効です。
4管理者だけに許可した操作を比較
対象のDACLはAdministratorsへ必要な権限を許可し、それ以外の許可はないとします。該当するSIDを許可側に使えるかを両トークンで並べます。
$tokens | Select-Object Nameトークンごとに表示,@{Name="AdminAllowApplies";Expression={ [bool]([int]$_.AdminAttributes -band 4) }}管理者の許可が適用されるか通常側ではこの許可を使えず、昇格側では使えます。これは指定したDACLの条件での比較です。別の利用者・グループへの許可や明示的な拒否がある場合は、それらも含めて判定します。
5整合性レベルの数値
8192を16進で表すと0x2000でMedium、12288は0x3000でHighです。トークンの値を16進表示します。
$tokens | Select-Object Name同じ二行,@{Name="IntegrityHex";Expression={ "0x{0:x}" -f [int]$_.Integrity }}整合性レベルを16進へ整合性レベルは利用者SIDともDACLとも別の情報です。対象オブジェクトのmandatory labelはSACLに置かれ、NoWriteUpなどの方針により低いレベルから高いレベルへの書込みを制限します。
6DACLが許可しても書込みを制限する場合
ayaに書込みを許可したDACLを持ち、HighかつNoWriteUpのファイルを考えます。ほかの制約を満たす条件で、トークンのレベルを比較します。
$targetIntegrity = 12288対象はHigh; [int]$normal.Integrity -ge $targetIntegrity通常側のレベル比較; [int]$elevated.Integrity -ge $targetIntegrity昇格側のレベル比較MediumからHighへの書込みはNoWriteUpで止められます。High側はこのレベル制約を満たしますが、DACLの許可も別途必要です。MICの制約を通ることだけで全アクセスが許可されるわけではありません。
7特権の保持と有効状態
同じ表のDebugEnabledはSeDebugPrivilegeが有効かを表します。この例では昇格後もFalseです。
$tokens | Format-Table Name,DebugEnabledSeDebugPrivilegeの有効状態昇格したことと、各特権が現在有効であることは同じではありません。特権には保持されているか、有効かという状態があり、対象操作がどの特権を検査するかも確認します。この表は有効状態だけを示しているため、保持の有無までは読み取れません。
8昇格だけでは消えないDACLの拒否
今度はDACLがaya本人の要求を拒否している場合です。対象レベルはHighのまま、DACL許可とMICの両方を条件にします。
$daclAllows = $false今回のDACL判定; $tokens | Select-Object Name各トークン,@{Name="WriteAllowed";Expression={ $daclAllows -and ([int]$_.Integrity -ge $targetIntegrity) }}DACLとレベル制約を合わせる両方Falseです。昇格トークンがHighであっても、この要求を許可するDACL条件は満たしません。所有権の取得やバックアップ特権など別の操作を行う場合の扱いは、ここでの通常書込みとは分けて考えます。
まとめ
管理者グループのSIDがあっても、deny-onlyなら許可ACEの根拠には使われません。
整合性レベルとNoWriteUpはDACLとは別に書込みを制限します。
昇格・各特権の有効化・DACLの許可を、一つの状態として扱わないようにします。
操作履歴と解説を振り返れます。
PowerShell 7 / LAB\aya
$tokens = Import-Csv .\tokens.csv; $tokens | Format-Table Name,User,AdminAttributes,IntegrityName User AdminAttributes Integrity ---- ---- --------------- --------- normal LAB\aya 16 8192 elevated LAB\aya 7 12288
$normal = $tokens | Where-Object Name -eq normal; $elevated = $tokens | Where-Object Name -eq elevated; $normal.User -eq $elevated.UserTrue
[bool]([int]$normal.AdminAttributes -band 4); [bool]([int]$elevated.AdminAttributes -band 4)False True
$tokens | Select-Object Name,@{Name="AdminAllowApplies";Expression={ [bool]([int]$_.AdminAttributes -band 4) }}Name AdminAllowApplies ---- ----------------- normal False elevated True
$tokens | Select-Object Name,@{Name="IntegrityHex";Expression={ "0x{0:x}" -f [int]$_.Integrity }}Name IntegrityHex ---- ------------ normal 0x2000 elevated 0x3000
$targetIntegrity = 12288; [int]$normal.Integrity -ge $targetIntegrity; [int]$elevated.Integrity -ge $targetIntegrityFalse True
$tokens | Format-Table Name,DebugEnabledName DebugEnabled ---- ------------ normal False elevated False
$daclAllows = $false; $tokens | Select-Object Name,@{Name="WriteAllowed";Expression={ $daclAllows -and ([int]$_.Integrity -ge $targetIntegrity) }}Name WriteAllowed ---- ------------ normal False elevated False
演習完了