脆弱性の「毒」を断つ:VBScriptにおけるADODB.Commandを用いた防御的プログラミングの真髄
レガシーシステムの深淵で、今なお現役で稼働し続けるVBScript。現代のモダンな言語から見れば「化石」のように見えるかもしれないが、OSの深部に直接アクセスできるその特性は、正しく扱えば極めて強力な武器となる。
しかし、多くの現場で散見されるのが、SQL文を文字列結合(Concatenation)で生成するという「死へのパスポート」だ。本稿では、VBScriptにおけるSQLインジェクション脆弱性を撲滅し、メモリ管理と実行効率を極限まで高めるための「ADODB.Command」による実装技術を伝授する。
—
1. なぜ「文字列結合」はシステムを崩壊させるのか
`strSQL = “SELECT FROM Users WHERE ID = ‘” & Request.Form(“id”) & “‘”`
この書き方は、VBScriptの初学者が最初に陥る罠だ。攻撃者は`’ OR ‘1’=’1`といった入力を差し込むだけで、認証をバイパスし、データベースの全権限を掌握する。これはSQLの構造とデータが分離されていないことに起因する。
この脆弱性を根本から叩き潰す唯一の手段が「パラメータ化クエリ(Parameterized Query)」である。
—
2. ADODB.Commandによる強固な実装
`ADODB.Recordset`で直接SQLを投げるのは卒業すべきだ。`ADODB.Command`を使用し、データベースエンジンに実行計画の最適化と安全な値のバインドを委ねるのが、プロフェッショナルの流儀である。
実装例:セキュアなデータベース操作
Option Explicit
‘ メモリリークを防ぐため、オブジェクトの初期化を徹底する
Dim conn, cmd, param, rs
Set conn = CreateObject(“ADODB.Connection”)
Set cmd = CreateObject(“ADODB.Command”)
‘ 接続文字列(環境に応じ適宜設定)
conn.Open “Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;”
‘ コマンドオブジェクトの設定
Set cmd.ActiveConnection = conn
cmd.CommandText = “SELECT UserName FROM Users WHERE UserID = ? AND Status = ?”
cmd.CommandType = 1 ‘ adCmdText
‘ パラメータの明示的定義(型とサイズを厳密に指定することが重要)
‘ 第1引数: 名前, 第2引数: 型(adInteger/adVarChar), 第3引数: 方向, 第4引数: サイズ, 第5引数: 値
cmd.Parameters.Append cmd.CreateParameter(“@ID”, 3, 1, 0, 101) ‘ adInteger
cmd.Parameters.Append cmd.CreateParameter(“@Stat”, 200, 1, 50, “Active”) ‘ adVarChar
‘ 実行
Set rs = cmd.Execute
If Not rs.EOF Then
WScript.Echo “User Found: ” & rs.Fields(“UserName”).Value
End If
‘ — 後始末:ライフサイクルの管理 —
‘ オブジェクトを明示的に解放し、プロセスメモリを適正に保持する
rs.Close: Set rs = Nothing
Set cmd = Nothing
conn.Close: Set conn = Nothing
—
3. シニアエンジニアが意識すべき「極限の知見」
オブジェクトのライフサイクルとメモリ解放
VBScriptはガベージコレクションを備えていない。`Set obj = Nothing`を怠ることは、IIS(W3C)環境においてメモリの枯渇を招く。特にループ内で`CreateObject`を行うような愚行は厳禁だ。オブジェクトはループの外で生成し、再利用(Re-use)することを意識せよ。
SQL実行計画の再利用
`ADODB.Command`を使用することで、RDBMS側ではパラメータ化されたクエリが「キャッシュ」されやすくなる。文字列結合でクエリを動的に生成し続けると、RDBMSは毎回新しいSQLと判断し、実行計画の再計算が発生する。これは高負荷なシステムにおいてボトルネックの最大の要因となる。パラメータ化はセキュリティのためだけでなく、パフォーマンス最適化の定石でもある。
型の一致(Type Safety)
`CreateParameter`で指定する型コード(`adInteger=3`, `adVarChar=200`など)は、可能な限りRDBMS側のカラム定義と一致させよ。暗黙的な型変換が発生すると、RDBMSのインデックスが無視されるケース(Index Scanの発生)があり、検索速度が劇的に低下する。
—
結論:コードは「防御」であれ
レガシー環境の保守は、単なるコードの修正ではない。それはシステムの「脆弱性」という負債を一つずつ完済していく作業だ。
今回紹介した`ADODB.Command`による実装は、記述量は増えるが、それは安全という名の堅牢な防壁を築くためのコストに過ぎない。VBScriptを扱う我々にとって、コードの簡潔さよりも重要なのは、システムの「安定」と「信頼性」である。
明日から貴殿が書くコードが、攻撃者にとっての「攻略不可能な壁」となることを期待している。
