【共有フォルダ全調査】WMI Win32_Share を用いた隠し共有(C$等)を含むローカル・リモート共有一覧の完全取得
開発現場やインフラ保守の現場において、端末のセキュリティ監査や不要な共有フォルダの洗い出しは避けて通れない重要タスクだ。
特に、管理者用としてOSが自動生成する隠し共有(`C$`、`ADMIN$`、`IPC$`など)が意図せず外部に露出していないか、あるいは業務用の共有フォルダに脆弱なアクセス権が設定されていないかを網羅的に調査する必要がある。
GUIのコンピューター管理から1台ずつポチポチ確認するなどというのは、エンジニアの恥だ。
今回は、WMI(Windows Management Instrumentation)の `Win32_Share` クラスをVBScriptで極限まで効率よく叩き、ローカルおよびリモートマシンの共有状態を一網打尽にするプロダクションコードを伝授する。
—
なぜ「あの書き方」ではバグるのか? WMIとVBScriptの闇
多くのネット上のサンプルコードは、エラーハンドリングをサボっているか、あるいはWMIのコネクションプーリングやCOMオブジェクトの解放を怠っている。
1. リモート接続時の認証・権限エラーの放置
`GetObject(“winmgmts://…”)` を使う際、対象マシンがオフラインだったり、権限不足だったりすると、スクリプトは容赦なくクラッシュ(13番や424番などの実行時エラー)する。
2. `For Each` のブラックボックス化とNULL落ち
WMIのプロパティ(特に `Path` や `MaximumAllowed` など)は、共有の種類(プリンタ共有やIPC$など)によって値が `Null` を返す。これをそのまま文字列結合すると、型ミスマッチの嵐となる。
3. セキュリティ監査としてのスコープ不足
単に共有名とパスを取るだけでは不十分だ。「なぜその共有が存在するのか(説明文)」や「タイプ(ディスク共有かIPCか)」まで引けなければ、レポートとしての価値はない。
これらを完全に克服し、実務の監査レポート(CSV出力)にそのまま耐えうる堅牢なアーキテクチャを解説する。
—
プロダクションコード:`Audit-Shares.vbs`
以下のコードは、エラーハンドリング(`On Error Resume Next` の厳格な制御)、リモート対応、そして文字化けを防ぐUTF-8/Shift-JIS配慮のファイルI/Oを組み込んだ実用スクリプトである。
メモ帳に貼り付け、拡張子を `.vbs` として保存して実行してほしい。
‘ ==============================================================================
‘ Script Name : Audit-Shares.vbs
‘ Purpose : WMI Win32_Share を用いた隠し共有含む共有一覧のセキュリティ監査
‘ Description : ローカルまたはリモートマシンの共有フォルダを走査し、CSVに出力する
‘ Author : 開発チーフアーキテクト
‘ ==============================================================================
Option Explicit
‘ — 設定エリア —
Const TargetComputer = “.” : ‘ “.” はローカル。リモートの場合は “192.168.1.50” やホスト名を指定
Const OutputFilePath = “C:\Temp\Share_Audit_Report.csv”
Sub Main()
Dim objFSO, objFile
Dim colShares, objShare
Dim wmiService, wmiLocator
Dim strType, maxAllowed
‘ ファイルシステムの準備
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
‘ 出力先フォルダの存在確認・作成
Dim parentDir
parentDir = objFSO.GetParentFolderName(OutputFilePath)
If Not objFSO.FolderExists(parentDir) Then
objFSO.CreateFolder(parentDir)
End If
‘ CSVファイルのオープン (ForWriting = 2, Create = True, Format = -1(SystemDefault))
Set objFile = objFSO.OpenTextFile(OutputFilePath, 2, True)
‘ CSVヘッダーの書き込み
objFile.WriteLine “ComputerName,ShareName,Path,Description,ShareType,MaximumAllowed”
‘ WMI接続の確立(セキュリティと堅牢性を考慮したLocator使用)
On Error Resume Next
Set wmiLocator = CreateObject(“WbemScripting.SWbemLocator”)
Set wmiService = wmiLocator.ConnectServer(TargetComputer, “root\cimv2”)
If Err.Number <> 0 Then
WScript.Echo “[-] 致命的エラー: WMIへの接続に失敗しました。対象マシン名、ネットワーク、または権限を確認してください。” & vbCrLf & “詳細: ” & Err.Description
WScript.Quit 1
End If
On Error GoTo 0
‘ 共有情報の取得
Set colShares = wmiService.InstancesOf(“Win32_Share”)
Dim count
count = 0
For Each objShare in colShares
‘ 共有タイプの数値判定
‘ 0: Disk Drive, 1: Print Queue, 2: Device, 3: IPC, 2147483648: Disk Drive Admin, etc.
strType = GetShareTypeString(objShare.Type)
‘ 接続数上限のハンドリング(無制限の場合はNullや特殊値があり得る)
maxAllowed = objShare.MaximumAllowed
If IsNull(maxAllowed) Then
maxAllowed = “Unlimited”
End If
‘ CSVへの書き出し(カンマやダブルクォーテーションのエスケープ処理を含む)
objFile.WriteLine “””” & TargetComputer & “””,” & _
“””” & SafeStr(objShare.Name) & “””,” & _
“””” & SafeStr(objShare.Path) & “””,” & _
“””” & SafeStr(objShare.Description) & “””,” & _
“””” & strType & “””,” & _
“””” & maxAllowed & “”””
count = count + 1
Next
‘ クリーンアップ
objFile.Close
Set objFile = Nothing
Set objFSO = Nothing
Set colShares = Nothing
Set wmiService = Nothing
Set wmiLocator = Nothing
WScript.Echo “[+] 監査完了: ” & count & ” 件の共有を検出し、以下のパスに保存しました。” & vbCrLf & OutputFilePath
End Sub
‘ ——————————————————————————
‘ 補助関数: 共有タイプを人間が読める文字列に変換
‘ ——————————————————————————
Function GetShareTypeString(ByVal shareType)
Select Case CInt(shareType)
Case 0: GetShareTypeString = “Disk Drive”
Case 1: GetShareTypeString = “Print Queue”
Case 2: GetShareTypeString = “Device”
Case 3: GetShareTypeString = “IPC”
Case 2147483648: GetShareTypeString = “Disk Drive Admin (隠し)”
Case 2147483649: GetShareTypeString = “Print Queue Admin (隠し)”
Case 2147483651: GetShareTypeString = “IPC Admin (隠し)”
Case Else: GetShareTypeString = “Other (” & shareType & “)”
End Select
End Function
‘ ——————————————————————————
‘ 補助関数: Nullや未定義値を安全な空文字に置換する
‘ ——————————————————————————
Function SafeStr(ByVal val)
If IsNull(val) Then
SafeStr = “”
Else
‘ ダブルクォーテーションのエスケープ(CSV用)
SafeStr = Replace(val, “”””, “”””””)
End If
End Function
‘ 実行
Main()
—
チーフアーキテクトが教える実装の急所
1. 隠し共有の判定ロジック
`Win32_Share` の `Type` プロパティは、管理共有(末尾に `$` がつくもの)において特殊なフラグ(ビット演算的あるいは大数値)を返す。上記の `GetShareTypeString` 関数では、一般的な管理者用共有の値をカバーしているため、「なぜこのC$が存在しているのか」の棚卸しが一目で可能になる。
2. `SWbemLocator` の採用理由
単なる `GetObject(“winmgmts:”)` よりも、`SWbemLocator.ConnectServer` を使う方が、将来的にリモートマシンの別資格情報(別ドメインのアカウントなど)を指定して接続拡張する際に圧倒的に有利だ。プロ仕様のコードでは常にロケーターオブジェクトを明示的にインスタンス化すべきである。
3. CSVインジェクション・文字列表現への配慮
共有の `Description`(説明文)や `Path` には、予期せぬダブルクォーテーションや特殊文字が含まれていることがある。`SafeStr` 関数でしっかりとエスケープ処理を行っているため、ExcelでCSVを開いた際にレイアウトが崩壊する事故を防いでいる。
—
運用・データベース連携への発展
このVBScriptで出力したCSVファイルを、PowerShellやPython、あるいは夜間バッチでSQL ServerやSQLiteなどのデータベースにインポートするパイプラインを構築すれば、全社端末の共有フォルダ構成管理台帳が自動完成する。
「手作業でサーバーを巡回して確認する」という前時代的な業務は今日で終わりにしよう。
堅牢に設計されたスクリプトこそが、あなたのインフラを守る最強の盾となる。
