【実務・中級編】 パス・トラバーサル(ディレクトリ・トラバーサル)による機密ファイル読み取り – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

パス・トラバーサル:その「ファイル読み込み」がシステムを陥落させる瞬間

やあ。今日も本番環境のログとにらめっこしているか?
セキュリティの世界では「脆弱性は常に弱いリンクから侵入してくる」と言われるが、その中でも特に古くから存在し、かつ未だに多くのWebアプリを沈没させているのが「パス・トラバーサル(ディレクトリ・トラバーサル)」だ。

教科書には「../ を使った攻撃」と一行で書かれているが、現場のペネトレーションテストではそんな単純な話じゃない。今日は、攻撃者がどうやってその脆弱性を突き、君たちが明日から実装で守り切るべきか、実践的な視点で解説しよう。

—

1. なぜ「パス・トラバーサル」は今も死なないのか?

攻撃者は、Webアプリケーションがファイルを読み込む際の「外部入力をそのままファイルパスとして扱う」という甘えを狙っている。例えば、画像を表示する機能で file.php?name=profile.jpg といったパラメータがある場合、攻撃者はこれを書き換えて file.php?name=../../../etc/passwd と投げる。

ここで重要なのは、サーバーが「このユーザーはWebルートの中を見ようとしているはずだ」という性善説に基づいた設計をしていることだ。OSから見れば、Webサーバーのプロセス権限でアクセス可能なすべてのファイルが標的になる。設定ファイル(.env)、SSH鍵、DBの接続情報……これらが漏洩した時点で、ゲームオーバーだ。

—

2. 攻撃者が狙う「盲点」のPoC

実務上のペネトレーションテストでは、単なる ../ の繰り返しだけではWAFに弾かれることが多い。攻撃者は以下のような手法を組み合わせる。

  • URLエンコードの二重化: ..%2f..%2f のようにエンコードを挟むことで、検知をすり抜ける。
  • NULLバイト攻撃: 古いPHP環境などでは filename.php%00 を付与することで、末尾の拡張子チェックを無効化する。
  • 絶対パス指定: /etc/passwd のようにルートから直接指定する。

これらが成功すると、攻撃者は君たちのアプリケーションのバックエンドにある「宝の山」を覗き始めるわけだ。

—

3. 「防ぐ」ための鉄則:セキュアな実装ガイド

防御の基本は「ユーザー入力を一切信用しないこと」と「パスを物理的に隔離すること」だ。

PHPでのセキュアな実装例

PHPでファイルを読み込む際は、basename() でファイル名のみを抽出し、さらに読み込み先ディレクトリを厳密に制限するべきだ。

<?php
// 許可されたディレクトリのみを定義(ホワイトリスト)
$base_dir = '/var/www/html/uploads/';
$requested_file = $_GET['file'];

// basenameでディレクトリトラバーサルを防ぐ
$safe_filename = basename($requested_file);
$path = $base_dir . $safe_filename;

// ファイルが存在し、かつ安全なディレクトリ内にあるか確認
if (file_exists($path) && strpos(realpath($path), realpath($base_dir)) === 0) {
    header('Content-Type: image/jpeg');
    readfile($path);
} else {
    // 不正なアクセスはログに残し、404を返す(攻撃者にヒントを与えない)
    http_response_code(404);
    die("File not found.");
}
?>

Nginxによるインフラ側での防御

アプリ層だけで守るのではなく、WAFやサーバー設定でも多層防御を敷く。Nginxで ../ を含むリクエストを拒否する設定だ。

# nginx.conf の server ブロック内に記述
location / {
    # ../ を含むリクエストを拒否
    if ($query_string ~ "\.\./") {
        return 403;
    }
    # NULLバイト攻撃のフィルタリング
    if ($query_string ~ "%00") {
        return 403;
    }
}

—

4. 現場のエンジニアへ送る「守りの知恵」

最後に、一つだけ覚えておいてほしい。
どんなにコードを堅牢にしても、「権限設定」が甘ければ意味がない。

1. 最小権限の原則: Webサーバー(www-data 等)の実行ユーザーが、システム設定ファイル(/etc/ など)を読み取れないようにパーミッションを設定せよ。
2. ファイルはWebルートの外に置く: アップロードされたファイルや重要な設定ファイルは、Web公開ディレクトリから物理的に切り離した場所に配置するのが鉄則だ。
3. WAFの導入: AWS WAFなどのマネージドサービスを使えば、既知のトラバーサルパターンは自動的に弾いてくれる。これを使わない手はない。

「面倒くさい」と感じるその一手間が、君のサービスを数百万件の個人情報流出から守る最後の砦になる。セキュリティは、何か起きてからやるものじゃない。設計段階から「どうやって壊すか」を考えながら作るものだ。

もし不安なら、まずは自社の開発環境で curl を使って ../ を投げつけてみるといい。何が見えてしまうか、その目で確かめるのが、最高の学習になるはずだ。

また何かあればいつでも聞いてくれ。現場からは以上だ。

コメント

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