【テクニカル・上級編】 パストラバーサルによる機密ファイル漏洩 – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

パストラバーサル:アーキテクチャの隙間を縫う「論理的崩壊」の深淵

「パストラバーサル(ディレクトリトラバーサル)など、今さら語るまでもない初歩的な脆弱性だ」と鼻で笑うアーキテクトがいるならば、その人物こそが最も危うい。現代のクラウドネイティブな環境において、ファイルパスの操作は単なる文字列連結ではなく、抽象化レイヤーの複雑な絡み合いの中で行われているからだ。

我々レッドチームが標的をハッキングする際、パストラバーサルは単なる「設定ファイルの読み取り」以上の意味を持つ。それは、サンドボックスの境界を突破し、コンテナの特権エスケープや、サイドカーコンテナ間の認証トークンを奪取するための「足がかり」となる。

本稿では、この古くて新しい脆弱性の本質を、低レイヤーの挙動とモダンな防御設計という観点から解体する。

—

1. 脆弱性の深層:APIの「曖昧な正規化」が招く悲劇

脆弱性の根本原因は、往々にして「入力値の検証」と「ファイルシステムAPIの解釈」の間にある齟齬(ミスマッチ)に潜んでいる。

多くの開発者は、../ を排除すれば安全だと信じている。しかし、OSのAPIやランタイムがどのようにパスを解釈するかを理解していない。例えば、Windows環境における \\?\ 接頭辞や、UNCパス、あるいは特定の言語ランタイムにおける「ヌルバイトインジェクション(%00)」、さらにはファイルシステムレベルのシンボリックリンク操作によるリダイレクトなどが、防御フィルターを無力化する。

なぜ「バリデーション」は失敗するのか

攻撃者は、アプリケーション層のフィルターをバイパスするために、以下の手法を多用する。

  • エンコーディングの多重化: URLエンコード、ダブルURLエンコード、Unicodeエスケープ(%u002e)など、バックエンドのデコーダーが処理する順序の隙間を突く。
  • ファイルシステム固有の正規化: Linuxの /proc/self/root を経由するパス指定や、OSが自動的に解決するショートパス(Windowsの8.3形式など)の利用。

—

2. 実践的防御アーキテクチャ:論理的境界の堅牢化

「入力を浄化する(Sanitize)」というアプローチは、イタチごっこの末路を辿る。真の防御は、「不可能なパスを生成させない」設計にある。

悪い実装例:ブラックリスト方式

// 危険:ブラックリストで '../' を弾こうとしても、エンコーディングで回避される
$path = str_replace('../', '', $_GET['file']);
include('/var/www/uploads/' . $path);

正しい実装例:ホワイトリストと正規化の徹底

実務では、ファイル名を直接パスに含めるのではなく、システム内で生成した一意なID(UUID)をマッピングテーブルで管理し、ベースディレクトリを物理的に固定することが鉄則だ。

/**
 * 堅牢なファイル読み込みの例
 */
function getSecureFile(string $userInputId): string {
    $baseDir = realpath('/app/storage/uploads');
    
    // 1. マッピングテーブルにより、ユーザ入力から物理パスを切り離す
    $filename = fetchFilenameFromDatabase($userInputId); 
    
    // 2. パスを結合し、realpathで絶対パスに正規化
    $targetPath = realpath($baseDir . DIRECTORY_SEPARATOR . $filename);

    // 3. 物理的境界の強制検証(ここが最も重要)
    if ($targetPath === false || strpos($targetPath, $baseDir) !== 0) {
        throw new SecurityException("不正なアクセス試行を検知しました");
    }

    return $targetPath;
}

—

3. 次世代の防御層:AIガードレイルとコンテキスト認識

最近では、生成AIを用いたインフラ運用が一般化しているが、ここにも新たなパストラバーサルの脅威が存在する。プロンプトインジェクションにより、AIエージェントが意図せず os.path.join() を呼び出し、サーバー内の重要ファイルを読み取ってしまう事例だ。

これを防ぐには、アプリケーションコードの外側に「ポリシー実行エンジン」を配置するアーキテクチャが有効である。

  • OSレベルのサンドボックス: seccomp や AppArmor を使用し、プロセスがアクセス可能なファイルシステム領域をカーネルレベルで制限する。
  • ゼロトラスト・ファイルアクセス: アプリケーションは直接ファイルシステムに触れず、署名付きのトークンを介して専用のストレージAPI(オブジェクトストレージ等)経由でのみアクセスする。

アーキテクチャ構築のチェックリスト

1. 分離: ファイルストレージをメインアプリケーションと別サーバー(あるいは別コンテナ)に切り離し、ネットワーク越しにアクセスさせる。
2. 正規化の強制: 入力パスは必ず realpath() 相当の関数を通し、シンボリックリンクを含めて解決した後の絶対パスで比較する。
3. 最小権限: アプリケーションが実行されているユーザー権限は、必要なディレクトリ以外への読み取り権限(r)を持たないように設定する。

—

結論:コードの背後にある「現実」を見る

パストラバーサルは、単なる「入力チェックの甘さ」の問題ではない。それは、システムが「どこまでを自分の所有物と認識しているか」という境界線の定義(Domain Boundary Definition)の崩壊だ。

トップクラスのセキュリティエンジニアは、コードの行間を読み、OSカーネルのメモリ挙動まで想像を巡らせる。脆弱性を探すときは、正規表現のパズルを解くのではなく、「設計者が想定しなかったパスの辿り方」を物理世界のようにシミュレーションせよ。

防衛は、静的解析ツールを回して満足する作業ではない。それは、システム全体が本来あるべき姿で動くよう、論理の迷路を一つひとつ埋めていく、泥臭くも高潔な構築作業である。

コメント

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