【VBScript極限運用】継承切れを見逃すな:WMIとicaclsによるパーミッション異常の自動検知
システム運用において、最も見落とされがちな「静かなる爆弾」が、フォルダのアクセス権継承の切断である。親フォルダから継承されるべきセキュリティ設定が、何らかの操作で遮断された瞬間、その領域は監査の死角となる。
本稿では、VBScriptとWSH(Windows Script Host)の泥臭い連携により、このセキュリティリスクを極限まで効率的に抽出するアーキテクチャを提示する。
—
なぜWMIだけでは不十分なのか
多くの管理者は `Win32_LogicalFileSecuritySetting` を利用してパーミッションを解析しようとする。しかし、このWMIクラスは巨大なディレクトリ構造に対して実行すると、メモリリークとWMIプロバイダーのハングアップを引き起こす「地雷」である。
我々が採用すべきは、「WMIによる高速なパス列挙」と「icacls.exeによる権限評価のパイプライン処理」のハイブリッド構成である。これにより、オブジェクト生成のオーバーヘッドを最小化しつつ、OSのネイティブ機能を最大限に活用する。
—
アーキテクチャ:継承判定ロジック
`icacls` の出力結果に含まれる `(I)` というフラグが、継承が有効である証明である。このフラグが消滅したフォルダを検知することが、今回の自動化の核心である。
実装コード
‘ セキュリティリスク検知スクリプト: CheckInheritance.vbs
Option Explicit
Dim fso, shell, logFile
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set shell = CreateObject(“WScript.Shell”)
‘ ログファイルの初期化
Set logFile = fso.CreateTextFile(“SecurityAudit.log”, True)
‘ 監査対象のルートパス
Dim targetRoot: targetRoot = “C:\SharedFolder”
‘ WMIを利用してサブフォルダを高速列挙
Dim objWMIService, colSubfolders, objFolder
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)
Set colSubfolders = objWMIService.ExecQuery(“Associators of {Win32_Directory.Name='” & Replace(targetRoot, “\”, “\\”) & “‘} Where ResultClass = Win32_Directory”)
For Each objFolder In colSubfolders
CheckPermission objFolder.Name
Next
‘ オブジェクトの明示的解放(VBScriptのメモリ管理の鉄則)
Set colSubfolders = Nothing
Set objWMIService = Nothing
logFile.Close
WScript.Echo “Audit Completed.”
Sub CheckPermission(path)
Dim cmd, exec, output, line
‘ icaclsで権限情報を取得
cmd = “icacls “”” & path & “”””
Set exec = shell.Exec(cmd)
output = exec.StdOut.ReadAll
‘ (I)フラグが含まれているか判定
‘ 継承が切れている場合、icaclsの結果に (I) が含まれない可能性が高い
‘ ※環境依存があるため、詳細なDACL解析が必要な場合はここを拡張する
If InStr(output, “(I)”) = 0 Then
logFile.WriteLine “ALERT: Inheritance broken at: ” & path
End If
Set exec = Nothing
End Sub
—
チーフアーキテクトの極意:保守と最適化
このスクリプトを運用する上で、シニアエンジニアが意識すべき「3つの技術的要諦」を記す。
1. オブジェクトライフサイクルの管理
VBScriptのガベージコレクションは非常に脆弱である。`Set obj = Nothing` を怠ることは、長時間のバッチ実行においてメモリ枯渇を意味する。特に `WScript.Shell` の `Exec` メソッドはプロセスを生成するため、ループ内での解放は必須だ。
2. パイプライン処理の限界を知る
`shell.Exec` は非同期実行が可能だが、今回はパイプ出力 (`StdOut`) を受け取るために同期的に処理している。もし対象が数万フォルダに及ぶ場合は、`Exec` ではなく `Run` を使用し、結果を一時ファイルに出力して後続で解析する「バッチ駆動型」へ切り替えるべきだ。
3. レガシー環境の罠
古い Windows Server では `icacls` ではなく `cacls` が標準の場合がある。しかし `cacls` は継承判定が極めて困難であるため、もし `icacls` が存在しない環境であれば、PowerShellの `Get-Acl` を呼び出すラッパーに書き換えるのが最も安全だ。VBScriptの `Run` から PowerShell を叩くことは、決して恥ずべきことではない。むしろ、適材適所のアーキテクチャこそがエンジニアの矜持である。
—
結びに代えて
自動化とは、単にスクリプトを書くことではない。「OSがどのような挙動でリソースを消費しているか」を理解し、その限界の数歩手前を歩くことである。
このスクリプトは、あなたの管理する共有フォルダからセキュリティの死角を排除する強力な武器となるはずだ。次に進むべきステップは、このログをメール通知、あるいはSIEM(セキュリティ情報イベント管理)へと連携させることである。
健闘を祈る。
