【実務・中級編】【スクリプト電子署名】Signer オブジェクトと連携したVBScriptコードへのデジタル署名検証と整合性チェック – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【スクリプト電子署名】Signer オブジェクトと連携したVBScriptコードへのデジタル署名検証と整合性チェック

開発プロジェクトのリーダーである私たちが、現場のメンバーによく言う言葉がある。
「動くコードを書くのはプログラマーの仕事だ。だが、『勝手に改ざんされないこと』を保証し、セキュアに稼働させ続けることは、プロフェッショナル・エンジニアの仕事だ」と。

業務自動化の現場において、VBScript(WSH)は今なお強力なカードだ。追加のランタイムをインストールせずとも、Windows環境さえあればタスクスケジューラと連携して骨太なバッチ処理を完遂できる。
しかし、その「手軽さ」ゆえの最大の弱点がセキュリティである。テキストファイルとして剥き出しで存在する `.vbs` は、悪意ある第三者(あるいは不心得な利用者)によって、いとも簡単にコードを書き換えられてしまう。パスワードのハードコーディング、不正なAPIエンドポイントへのすり替え――これらを防ぐ防壁がなければ、エンタープライズの自動化基盤としては失格だ。

今回は、Windows Script Host (WSH) が密かに内包する最高峰のセキュリティ機構、`Scripting.Signer` オブジェクトを用いたVBScriptのデジタル署名付与・検証・整合性チェックの極限知見を伝授する。

1. なぜ「剥き出しのVBScript」は危険なのか?

多くの現場では、VBScriptのセキュリティを「フォルダのアクセス権(ACL)」だけで担保しようとする。だが、それは幻想だ。
ネットワーク共有フォルダに置かれたスクリプト、ローカルの管理者権限を持つユーザー、あるいはシャドウITによる野良スクリプトの実行。これらはファイル権限をいとも簡単にすり抜ける。

ここで必要なのは、ファイルシステムへの依存ではなく、「コードそのものが証明書によって担保されているか」という暗号学的な整合性チェックである。

Scripting.Signer オブジェクトの本質

`Scripting.Signer` は、`.vbs` や `.js` といったWSHスクリプトファイルに対して、Authenticode形式のデジタル署名を付与し、かつその検証を行うためのCOMコンポーネントだ。
内部的にはCryptoAPIをラップしており、証明書ストアに紐づく信頼されたルート証明書をベースに、スクリプトが「誰によって書かれ」「署名以降に1バイトたりとも改ざんされていないか」を数学的に証明する。

2. 現場で使える!署名検証・整合性チェックのプロダクションコード

口を酸っぱくして言うが、セキュリティ機構は「エラーハンドリングをサボった瞬間にお飾りと化す」。
以下のコードは、指定されたVBScriptファイルのデジタル署名を厳密に検証し、改ざんや未署名を検知した場合は一切の実行を拒絶する、プロダクション品質の「セキュア・ローダー」である。

コピペしてそのまま現場の基盤に組み込んでほしい。

‘ ==============================================================================
‘ Script Name: SecureScriptLoader.vbs
‘ Description: 指定されたVBScriptファイルのデジタル署名を検証し、
‘ 整合性が確認された場合のみ実行するセキュアローダー
‘ ==============================================================================
Option Explicit

Const TARGET_SCRIPT = “C:\Automation\CoreProcess.vbs”
Const REQUIRE_VALID_SIGNATURE = True ‘ 本番環境では必ずTrueにすること

Sub Main()
Dim fso, shell
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set shell = CreateObject(“WScript.Shell”)

‘ 1. ターゲットファイルの存在確認
If Not fso.FileExists(TARGET_SCRIPT) Then
WScript.Echo “[FATAL ERROR] ターゲットスクリプトが見つかりません: ” & TARGET_SCRIPT
WScript.Quit 1
End If

‘ 2. デジタル署名の検証と整合性チェック
Dim isSignedAndValid
isSignedAndValid = VerifyScriptSignature(TARGET_SCRIPT)

If Not isSignedAndValid Then
If REQUIRE_VALID_SIGNATURE Then
WScript.Echo “[SECURITY ALERT] スクリプトのデジタル署名が無効、または改ざんされています。” & vbCrLf & _
“実行を強制中断します。”
‘ 異常終了コードを返す(タスクスケジューラの検知用)
WScript.Quit 99
Else
WScript.Echo “[WARNING] 署名が無効ですが、設定により実行を継続します。”
End If
Else
WScript.Echo “[INFO] デジタル署名の検証に成功しました。整合性は完全に保たれています。”
End If

‘ 3. 検証通過後に別プロセスとして安全に実行
‘ ※ 外部スクリプトに引数を渡す設計にする場合はここにパラメータを追加
Dim cmd
cmd = “cscript.exe //Nologo “”” & TARGET_SCRIPT & “”””

Dim exitCode
exitCode = shell.Run(cmd, 1, True)

WScript.Quit exitCode
End Sub

‘ ——————————————————————————
‘ Function: VerifyScriptSignature
‘ 概要: Scripting.Signer を用いてスクリプトの署名妥当性を検証する
‘ 戻り値: Boolean (True = 署名有効かつ改ざんなし, False = 無効/未署名/エラー)
‘ ——————————————————————————
Function VerifyScriptSignature(filePath)
On Error Resume Next

Dim signer, isValid
‘ Signer オブジェクトのインスタンス化
Set signer = CreateObject(“Scripting.Signer”)

If Err.Number <> 0 Then
WScript.Echo “[ERROR] Scripting.Signer の初期化に失敗しました。OSの環境を確認してください。Error: ” & Err.Description
VerifyScriptSignature = False
Exit Function
End If

‘ 署名の検証を実行
‘ 内部で証明書の失効チェックやルート証明書の信頼性を検証する
isValid = signer.VerifyFile(filePath)

If Err.Number <> 0 Then
‘ 署名が存在しない場合や、パースに失敗した場合のエラー捕捉
‘ ※ 未署名ファイルに対して VerifyFile を実行するとエラーが発生する仕様
VerifyScriptSignature = False
Err.Clear
Exit Function
End If

On Error GoTo 0
VerifyScriptSignature = isValid
End Function

‘ 実行のエントリーポイント呼び出し
Main()

3. 開発者・アーキテクトが押さえるべき設計上の急所

この仕組みを導入するにあたり、現場のエンジニアからよく出る疑問と、私たちがロジカルに返すべき「設計の急所」を解説する。

急所①:「未署名のファイル」をどう扱うか?

開発環境(ローカルPC)において、コードを修正するたびに正式なコードサイン証明書で署名し直すのは、開発効率を著しく落とす(アジャイルの敵だ)。
そのため、上記のコードにあるように `REQUIRE_VALID_SIGNATURE` のようなフラグ、あるいは環境変数や設定ファイルによるスイッチを用意し、「開発環境では署名なしを許容し、本番環境(PRD)のCI/CDパイプラインやタスクスケジューラ配下では厳格に拒絶する」という多層防御のスイッチング設計に落とし込むべきだ。

急所②:コードサイン証明書の調達と管理

`Scripting.Signer` が検証できるのは、Windowsの「証明書ストア(Personal / TrustedPublisher など)」に正しく紐づき、信頼されたルートから発行された証明書(または自己署名証明書で、信頼されたルート証明機関ストアにインポートされたもの)である。
業務自動化ツールであれば、社内のプライベートCA(認証局)から発行されたコードサイニング証明書を、実行するマシンの `TrustedPublisher`(信頼された発行元)ストアにインポートしておく必要がある。

【参考:自己署名証明書をPowerShellで作成しストアへ登録するコマンド(開発・検証用)】

自己署名コードサイン証明書の作成 (PowerShell)
$cert = New-SelfSignedCertificate -Type CodeSigningCert -DnsName “AutomationScriptRoot” -CertStoreLocation “Cert:\CurrentUser\My”

信頼された発行元ストアへエクスポート&インポート
Export-Certificate -Cert $cert -FilePath C:\Temp\autocert.cer
Import-Certificate -FilePath C:\Temp\autocert.cer -CertStoreLocation “Cert:\LocalMachine\TrustedPublisher”

※本番運用では、必ず社内インフラチームが管理する正式なコードサイニング証明書を使用すること。

急所③:署名(Sign)を自動化パイプラインに組み込む

人間が手動で署名作業を行う運用は、必ず属人化し、ヒューマンエラーを生む。
VBScriptへの署名自体も、ビルドスクリプト(PowerShell等)から `Set-AuthenticodeSignature` コマンドレットなどを用いて自動化するのがモダンなアプローチだ。
しかし、WSHの `Scripting.Signer` 自体には、プログラムから署名を付与するメソッド (`SignFile`) も用意されている。

‘ 【参考】スクリプト内からプログラム的に署名を付与する場合のコード
Sub SignMyScript(filePath, certSubjectName)
Dim signer
Set signer = CreateObject(“Scripting.Signer”)
‘ 第1引数: 証明書の件名(Subject)の一部、第2引数: タイムスタンプサーバーURL(任意)
signer.SignFile filePath, certSubjectName, “http://timestamp.digicert.com”
End Sub

※ただし、秘密鍵のアクセス権限管理の観点から、署名付与はビルドサーバー側(PowerShell)で行い、実行端末(WSH)側では `Scripting.Signer` による「検証」のみに特化させるのが、セキュリティアーキテクチャとしては最もクリーンである。

4. まとめ:野良スクリプトを根絶し、セキュアな自動化基盤へ

VBScriptはレガシーな言語だと言われることがある。だが、それは「適切に現代的なセキュリティガバナンスを効かせていない現場」の言い訳に過ぎない。

今回解説した `Scripting.Signer` を組み合わせた検証ロジックをプロジェクトの標準テンプレートとして組み込めば、以下のような圧倒的なメリットを手に入れることができる。

1. 改ざんの即時検知: 万が一、不正アクセスや誤操作でスクリプトが書き換えられた場合でも、実行前に確実に弾くことができる。
2. 責任の所在の明確化: 誰(どの証明書)によって署名されたコードなのかが暗号学的に担保されるため、監査要件を容易にクリアできる。
3. 自動化基盤の信頼性向上: 「動けばいい」から「安全でなければ動かさない」という、プロフェッショナルなエンジニアリング文化の定着。

コードの行数を減らすことだけが効率化ではない。「後から発生するセキュリティインシデントという最大のコスト」をゼロにする設計こそが、私たちエンジニアリングチームが追求すべき真の効率化である。

今すぐ君の現場のバッチリポジトリに、このセキュアローダーを組み込んでほしい。

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