【実務・中級編】【上級プロフェッショナル向け】Windowsイベントログ連携によるFSO重要データ削除・改変のリアルタイムSIEM通知スクリプト – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【上級プロフェッショナル向け】Windowsイベントログ連携によるFSO重要データ削除・改変のリアルタイムSIEM通知スクリプト

プロフェッショナルな現場において、ファイルサーバーやローカルストレージ上の「重要データの改変・削除検知」は、セキュリティ監査およびインシデント初動対応の要諦である。

多くのエンジニアは、ファイルシステムオブジェクト(FSO: FileSystemObject)を用いて単にファイルの有無を確認したり、ログファイルをテキスト形式でローカルに追記したりするだけの稚拙な実装で満足している。しかし、それでは「ログファイル自体が改ざんされた場合」に真相が闇に葬られるうえ、企業全体のSOC(Security Operation Center)やSIEM(Splunk, Microsoft Sentinel, Datadogなど)とのリアルタイム連携において完全に機能不全に陥る。

今回は、FSOの監視・操作イベントをトリガーとし、Windowsのネイティブイベントログ(セキュリティ/アプリケーションログ)へ直接フックさせ、エンタープライズ監視網へシームレスに流し込むための「極限まで堅牢化されたプロダクションコード」を伝授する。

—

なぜ「テキストファイルへの直接ロギング」は実務で破綻するのか

素人が書く自動化スクリプトの悪癖として、次のような実装が挙げられる。

‘ 【アンチパターン】絶対に真似してはならない実装
Dim fso, logFile
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set logFile = fso.OpenTextFile(“C:\Logs\operation.log”, 8, True)
logFile.WriteLine Now & ” – ファイルが削除されました: ” & targetPath
logFile.Close

このアプローチが実務で破綻する理由は明確だ。
1. 競合制御の欠如: 複数プロセスが同時に書き込みを行った際、I/Oエラー(エラー70: 書き込み権限がありません、またはロックされています)でスクリプトが即座にクラッシュする。
2. 監査証拠としての信頼性ゼロ: ローカルのテキストファイルは、管理者権限を持つ悪意あるユーザーによって容易に改ざん・削除が可能であり、フォレンジックの証拠能力を持たない。
3. SIEM統合の欠如: 監視エージェントがテキストのパース(行解析)を行う必要があるため、フォーマット変更に弱く、リアルタイム性も著しく劣る。

これを解決唯一の解こそが、`WshShell.LogEvent`を用いたWindowsイベントログへのダイレクト・インジェクションである。OSのイベントログ機構に流し込むことで、ACL(アクセス制御リスト)による保護、イベントビューアからの視認性、そして各種SIEMフォワードツールによる秒単位のクラウド転送が完全に担保される。

—

堅牢なFSO × イベントログ連携アーキテクチャ

今回のプロダクションコードでは、以下の設計思想を徹底している。

  • 厳格なエラーハンドリング (`On Error Resume Next` の局所化): FSOのI/Oエラーや、存在しないパスへのアクセス時にもスクリプトが死なない構造。
  • イベントカテゴリの分離: 正常操作と危険な削除・改変をイベントIDレベルで明確に分離。
  • WMI/WshShellの適切なライフサイクル管理: メモリリークを防ぐためのオブジェクト解放の徹底。

—

【プロダクションコード】実用FSO監査・イベント通知スクリプト

以下のコードは、指定した重要ファイル/フォルダに対して削除・改変の兆候を検知し、Windowsイベントログへ構造化されたメッセージを書き込む、そのままエンタープライズ環境に投入可能なスクリプトである。

‘ ==============================================================================
‘ Script Name : FSO_SecurityAudit_Notifier.vbs
‘ Description : FSOを用いたファイル操作監視とWindowsイベントログ連携によるSIEM通知
‘ Author : 首席アーキテクト
‘ ==============================================================================

Option Explicit

‘ 定数の定義
Const EVENT_SUCCESS = 0
Const EVENT_ERROR = 1
Const EVENT_WARNING = 2
Const EVENT_INFO = 4

Const TARGET_FILE = “C:\EnterpriseData\Confidential_Master.dat”
Const EVENT_SOURCE = “EnterpriseSecurityAuditor”

‘ メイン処理の実行
Call MonitorAndAuditFile(TARGET_FILE)

Sub MonitorAndAuditFile(filePath)
Dim fso, wshShell, fileObj
Dim fsoExists, fsoSize, fsoLastModified

‘ オブジェクトの生成
On Error Resume Next
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set wshShell = CreateObject(“WScript.Shell”)

If Err.Number <> 0 Then
Call WriteSystemLog(wshShell, EVENT_ERROR, 1001, “FSOまたはWshShellオブジェクトの生成に失敗しました。Error: ” & Err.Description)
Exit Sub
End If
On Error GoTo 0

‘ 【重要】イベントソースの登録確認(初回実行時等のためのフォールバック)
‘ ※ 本番環境ではレジストリにイベントソースが事前登録されている前提とする

‘ ファイルの存在確認とメタデータ取得
If fso.FileExists(filePath) Then
Set fileObj = fso.GetFile(filePath)
fsoSize = fileObj.Size
fsoLastModified = fileObj.DateLastModified

‘ 監視ロジック(例:サイズが異常に小さい、または特定条件を満たした場合の改変検知)
If fsoSize < 100 Then Dim alertMsg alertMsg = "【セキュリティ警告】重要データのサイズが閾値を下回りました。改変の可能性があります。" & vbCrLf & _ "パス: " & filePath & vbCrLf & _ "サイズ: " & fsoSize & " bytes" & vbCrLf & _ "最終更新日時: " & fsoLastModified ' イベントログへ警告を出力 (Event ID: 3001 = データ改変の兆候) Call WriteSystemLog(wshShell, EVENT_WARNING, 3001, alertMsg) Else ' 正常稼働ログの記録(必要に応じてデバッグレベルで出力) ' Call WriteSystemLog(wshShell, EVENT_INFO, 2001, "ファイル監査: 正常性確認完了 -> ” & filePath)
End If

Set fileObj = Nothing
Else
‘ 【最重要】重要ファイルの消失(削除)検知
Dim criticalMsg
criticalMsg = “【緊急事態】保護対象の重要ファイルが消失(削除)されました!” & vbCrLf & _
“消失パス: ” & filePath & vbCrLf & _
“実行ユーザー: ” & wshShell.ExpandEnvironmentStrings(“%USERNAME%”) & vbCrLf & _
“端末名: ” & wshShell.ExpandEnvironmentStrings(“%COMPUTERNAME%”)

‘ イベントログへ重大エラーを出力 (Event ID: 4001 = 重要データ削除)
Call WriteSystemLog(wshShell, EVENT_ERROR, 4001, criticalMsg)
End If

‘ オブジェクトの明示的解放(メモリリークの根絶)
Set fso = Nothing
Set wshShell = Nothing
End Sub

Sub WriteSystemLog(shObj, logType, eventId, message)
On Error Resume Next
‘ WshShell.LogEvent の構文: LogEvent(Type, Message, [Target])
‘ Type: 0(Success), 1(Error), 2(Warning), 4(Information)

Dim formattedMessage
formattedMessage = “[EventID:” & eventId & “] ” & message

shObj.LogEvent logType, formattedMessage, EVENT_SOURCE

If Err.Number <> 0 Then
‘ イベントログ書き込み自体が失敗した場合は、最悪のケースとしてWScript.Echoでフォールバック
‘ (本番ではOSのアプリケーションログへのフォールバック等を検討すること)
WScript.Echo “CRITICAL: イベントログへの書き込みに失敗しました – ” & Err.Description
Err.Clear
End If
On Error GoTo 0
End Sub

—

プロフェッショナルが解説する実装の急所

1. イベントソース(`EVENT_SOURCE`)の設計

`WshShell.LogEvent` を使用する場合、デフォルトではソース名が `WSH` としてアプリケーションログに記録される。これでは、どのスクリプト、どのセキュリティ監査ツールからのログであるかが判別がつかない。
本コードのように独自のソース文字列を指定することで、SIEM側のパーサー(Regex等)で容易にフィルタリングが可能になる。
(※注: 初回実行時にイベントソースのレジストリ登録がない環境では、イベントビューアの詳細説明に「説明文が見つかりません」と表示される場合があるが、ログとしての実データ・EventIDは確実に記録されるためSIEM連携には何ら支障はない)

2. オブジェクトのライフサイクル管理とメモリ最適化

VBScriptのガベージコレクションは信頼性が低い。特にタスクスケジューラから毎分実行されるような監視スクリプトにおいて、`Set fso = Nothing` を怠ると、COMコンポーネントの参照カウントが残存し、メモリリーク(Memory Leak)を引き起こす。
プロダクションコードでは、サブルーチンの終了直前に必ず `Nothing` を代入し、リソースを完全にOSへ返還している。

3. セキュリティ監査における「誰が」の特定

ファイル削除(Event ID: 4001)の検知時、単に「消された」事実だけでなく、環境変数から取得した `%USERNAME%` と `%COMPUTERNAME%` をメッセージに埋め込んでいる点に注目してほしい。
これにより、イベントログを収集したSIEM上で、「どの端末の、どのユーザーアカウントによって重要データが葬り去られたのか」を即座に特定し、EDR(Endpoint Detection and Response)と連動したアカウントの自動隔離フローへつなげることが可能となる。

—

運用時の注意点とインフラ連携の極意

  • タスクスケジューラとの統合: このスクリプトは単体で常時常駐するものではない(VBScriptで無限ループを回すのはリソースの無駄であり悪手である)。Windowsタスクスケジューラに登録し、「最特権で実行(Run with highest privileges)」にチェックを入れ、高頻度(例:5分おき)でバッチ実行させるのが最も堅牢である。
  • SIEMフォワーダーの設定: Splunk Universal ForwarderやMicrosoft Monitoring Agentに対し、アプリケーションログを監視させ、ソース名 `EnterpriseSecurityAuditor` かつ イベントID `4001` が検知された瞬間に、セキュリティ担当者のSlack/Teams、あるいはPushoverへWebhook飛散するパイプラインを構築せよ。

VBScriptはレガシーな言語と揶揄されることもあるが、OSの根幹API(WshShellやFSO)をダイレクトかつローコストに叩ける特性において、いまだにWindowsインフラ管理の最強の隠し剣である。
本稿の知見を実装に落とし込み、貴社のセキュリティ監視体制をワンランク上のステージへと引き上げてほしい。

タイトルとURLをコピーしました