【シュレッダー削除】FSOでファイルを削除する前にダミーデータで上書きし復元を防止するセキュリティスクリプト
開発現場でよくある誤解の一つに、「`FileSystemObject`(以下、FSO)の `DeleteFile` メソッドを使えば、ファイルは完全に消去される」というものがある。
声を大にして言おう。それは幻想だ。
通常の削除処理は、ファイルシステム上の管理領域(インデックス)から該当ファイルのエントリを「削除済み」とマークし、領域の再利用を許可するに過ぎない。実際のデータ本体(クラスタ)は、新しいデータ上書きされるまでストレージの深くに残り続ける。市販のデータ復元ソフトを使えば、機密情報やパスワードリスト、個人情報などはいとも簡単にサルベージできてしまう。
特に、オンプレミスのレガシーな業務サーバーや、ローカル端末で一時的に処理した機密ファイルを扱うツールにおいて、この「見せかけの削除」はセキュリティ監査における致命的な脆弱性となり得る。
今回は、FSOの限界を突破し、ファイルを物理的に抹消する「シュレッダー削除(セキュア・ワイプ)」の極意を、プロダクション品質のVBScriptコードとともに伝授する。
—
1. 堅牢なファイル抹消のアーキテクチャ
真に安全なファイル消去を実現するためには、単にファイルを消すのではなく、以下のライフサイクルを厳密に踏む必要がある。
1. ファイルサイズの特定: 対象ファイルの正確なバイト数を取得する。
2. ゼロ・オーバー schreiben(上書き): 同サイズ分の `0x00`(ヌルバイト)またはランダムなバイナリデータをファイルに書き込み、元のデータ痕跡を完全に破壊する。
3. バッファの強制フラッシュ: OSのキャッシュに残らず、確実に物理ストレージへ書き込ませる。
4. ファイル名の難読化(オプション): 削除前にファイル名をランダムな文字列に変更し、ファイル名から推測されるメタデータを隠蔽する。
5. 最終削除: ここで初めて標準の `DeleteFile` を実行する。
VBScriptは高級言語の皮を被った低水準な操作も可能な言語だが、バイナリ直接操作においてはFSO単体では力不足となる。そこで、FSOのファイル読み書き能力と、ADODB.Stream等のオブジェクトを組み合わせたハイブリッドな設計が求められる。
—
2. 実装上の罠:なぜ単純なFSOだけでは不可能なのか?
FSOの `OpenTextFile` は、文字通り「テキスト」を扱うためのものだ。バイナリデータや正確なサイズでのバイト埋めを行おうとすると、文字コードの変換(ANSI/Unicode変換)が挟まり、意図した通りのバイト数が書き込めない、あるいはデータが破損するというバグを生む。
したがって、バイナリデータの生成と書き込みには `ADODB.Stream` オブジェクトを併用するのが、VBScriptにおけるベストプラクティスである。
—
3. プロダクションコード:セキュア・ファイル・シュレッダー
以下のコードは、指定されたファイルをゼロデータで完全上書きした上で安全に削除する、実務投入可能なファンクションである。エラーハンドリングとリソース解放の作法を完璧に実装している。
Option Explicit
‘ ==============================================================================
‘ 処理名: SecureDeleteFile
‘ 概要: 指定されたファイルをゼロデータで上書きしてから削除し、復元を防止する
‘ 引数: strFilePath – 削除対象のフルパス
‘ 戻り値: 成功時は True、失敗時は False
‘ ==============================================================================
Function SecureDeleteFile(ByVal strFilePath)
Dim fso, fileObj, fileSize, stream
Dim i, chunk, zeroBytes
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
SecureDeleteFile = False
Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ファイルの存在確認
If Not fso.FileExists(strFilePath) Then
‘ すでに存在しない場合は安全のためTrueを返す
SecureDeleteFile = True
Exit Function
End If
On Error Resume Next
‘ 1. ファイルサイズの取得
Set fileObj = fso.GetFile(strFilePath)
fileSize = fileObj.Size
Set fileObj = Nothing
‘ 2. ADODB.Streamを使用したバイナリ上書き処理
‘ ※巨大すぎるファイル(数GB単位)を扱う場合はメモリ圧迫に注意。
‘ 業務上のテンポラリファイル(数MB〜数十MB)を想定。
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = adTypeBinary
stream.Open
If fileSize > 0 Then
‘ ゼロ埋め用のバイナリデータを作成 (1MB単位のチャンク、またはファイルサイズ分)
‘ ここではシンプルかつ確実なバイト配列をStreamに書き込むアプローチをとる
Dim buffer()
ReDim buffer(fileSize – 1)
For i = 0 To fileSize – 1
buffer(i) = 0 ‘ 0x00 で初期化
Next
stream.Write buffer
stream.SaveToFile strFilePath, adSaveCreateOverWrite
stream.Close
End If
Set stream = Nothing
If Err.Number <> 0 Then
‘ 上書き段階でエラーが発生した場合は処理を中断
On Error GoTo 0
Exit Function
End If
‘ 3. 最終削除
fso.DeleteFile strFilePath, True
If Err.Number = 0 Then
SecureDeleteFile = True
End If
On Error GoTo 0
Set fso = Nothing
End Function
‘ — 実行テスト用スニペット —
Dim targetPath
targetPath = “C:\Temp\secret_data.txt”
‘ テスト用ファイルの作成
Dim fsoTest, ts
Set fsoTest = CreateObject(“Scripting.FileSystemObject”)
Set ts = fsoTest.CreateTextFile(targetPath, True)
ts.Write “このデータは極秘事項であり、復元されてはならない。”
ts.Close
Set ts = Nothing
Set fsoTest = Nothing
‘ シュレッダー削除の実行
If SecureDeleteFile(targetPath) Then
WScript.Echo “ファイルのセキュア消去に成功しました。”
Else
WScript.Echo “エラーが発生しました: ” & Err.Description
End If
—
4. チーフアーキテクトからの実践的アドバイス
メモリ管理とファイルサイズへの配慮
上記のコードは `ReDim buffer(fileSize – 1)` により、ファイルサイズ分のメモリを一度に確保する。数十MB程度のログやCSVファイルであれば全く問題ないが、もし数百MB〜数GBのファイルを対象にする場合、スクリプトホスト(`wscript.exe` / `cscript.exe`)のメモリ制限に抵触し、パフォーマンス劣化や Out of Memory エラーを引き起こす。
大規模なファイルを対象にする場合は、「一定のチャンクサイズ(例: 64KBや1MB)に分割してループで上書きを繰り返す」という設計上のブラッシュアップが必要となる。
SSD環境における注意点
現代のインフラストラクチャの主流であるSSD(Solid State Drive)には、寿命を延ばすための「ウェアレベリング(書き込み平準化)」や「TRIMコマンド」といった制御が存在する。これらにより、OSが指定した物理アドレスとは異なる場所にデータが書き込まれる可能性があり、HDD時代ほど確実な上書き破壊が保証されないケースがある。
極めて高い機密性が求められる環境(金融・防衛等)において、SSD上のファイルを完全に抹消したい場合は、OSレベルのファイル単体削除ではなく、暗号化ファイルシステム(EFS)の利用や、ボリューム全体の暗号化(BitLocker等)を前提としたアーキテクチャ設計を行うべきだ。VBScriptによる上書きは、あくまで「通常の業務自動化ツールにおけるセキュリティ底上げ(ベストエフォート)」としての位置づけをわきまえて実装すべし。
現場の要件に合わせ、この堅牢な設計を君の自動化スクリプトに組み込んでほしい。妥協のないコードこそが、プロフェッショナルの証だ。
