このたび、GMO Flatt Security 開発者応援プログラム for バイブコーダー に選定いただき、 セキュリティ学習サービス 「KENRO」 を1か月無料で利用できることになりました!
「KENRO」は、実践的な脆弱性診断やセキュリティ演習を通じて、 開発者が 攻撃者の視点 から安全なシステム設計を学べるオンライン学習プラットフォームです。
本記事では、KENROの学習内容をもとに Directory Traversal(パストラバーサル)の脆弱性 についてまとめます。
Directory Traversal 脆弱性とは
Web アプリケーションがユーザー入力を使ってファイルパスを動的に構成し、ファイルを読み書きするケースがあります。
その際に入力に ../ のようなパス横断文字列が含まれると、本来アクセスさせるべきでない上位ディレクトリやシステムファイルへ到達できてしまう脆弱性が Directory Traversal(パストラバーサル) です。
// 悪い例(C#)
string fileName = Request.QueryString["filename"]; // ユーザー入力
string text = File.ReadAllText("./public/" + fileName);
filename に ../../../../etc/passwd のような文字列が入ると ./public/ 外のファイルが読めてしまいます。
攻撃で何ができるか(影響)
攻撃者はこの脆弱性を使って、以下のような機密情報を読み出したり、場合によってはより深刻な侵害につなげたりできます。
- サーバ設定ファイル(例:
/etc/nginx/*,/etc/httpd/*,/etc/ssh/*など) - アプリケーションの環境変数(
/proc/self/environ) — APIキーやトークンの露出 - アプリケーションのソースコード(秘密情報や別脆弱性の発見に繋がる)
- サーバ上の任意ファイル(ログ、バックアップ、鍵ファイル等)
- 動的にスクリプトを読み込む実装では任意コード実行に繋がる可能性
※ 影響範囲は実装と権限構成によって変わります。ファイルを読み出せるだけでも重大な情報漏洩リスクです。
実務での対策
以下は現場で有効な対策の一覧と実装パターンです。可能な限り多層で組み合わせてください。
1) そもそもファイル名を直接受け取らない
- URLやパラメータでファイル名を受け取る必要があるかを再検討する。
- 可能なら
IDを受け取りサーバ側でマッピングする(例:fileId=123を受け、サーバがsample01.txtを選ぶ)。
2) ホワイトリスト(最も安全)
期待するファイル名が限られるなら、許可リストで厳しくチェックする。
// C#(ホワイトリスト例)
var whitelist = new HashSet<string>{ "sample1.txt", "sample2.txt", "sample3.txt" };
if (!whitelist.Contains(fileName)) {
// エラー対応
}
3) 入力バリデーション(許容文字のみ)
ファイル名に許可する文字セットを限定する(例:英数字、.、- のみ)。
// C#(正規表現例)
if (!Regex.IsMatch(fileName, @"^[A-Za-z0-9._-]+$")) {
// 不正なファイル名
}
4) パスの正規化とベースディレクトリチェック(言語横断で有効)
入力から生成したパスを正規化(絶対パス化)して、想定するベースディレクトリの配下かどうかを検査する。
// C#(安全なパス検査例)
string baseDir = Path.GetFullPath("./public/"); // 末尾のスラッシュを揃える
string requestedPath = Path.GetFullPath(Path.Combine(baseDir, fileName));
if (!requestedPath.StartsWith(baseDir, StringComparison.Ordinal)) {
// 不正アクセスと見なす
}
// または GetRelativePath を使って配下か判定する方法
string rel = Path.GetRelativePath(baseDir, requestedPath);
if (rel.StartsWith("..")) {
// ベース配下ではない
}
注意: StartsWith を使うときは、例えば /public2/ といったケースに注意(末尾のスラッシュ等を揃えて比較する)。可能なら Path.GetRelativePath 等を使う。
5) 言語・ランタイムの機能利用
- PHP の
realpath()、open_basedirなど、実行環境が提供する制限機能を利用する。 - Java なら
SecurityManagerやファイルアクセス制御、フレームワークのファイルハンドラ機能を活用する。 - コンテナや OS レベルでプロセス権限を制限し、最小権限の原則(Principle of Least Privilege) を徹底する。
6) ファイルの権限・運用側対策
- Webプロセス(例:
www-data)に重要ファイルへの読み取り権限を与えない。 - 機密情報は環境変数や秘密管理システム(例:Vault、AWS Secrets Manager 等)で安全に保管する。
- 監査ログ・アクセスログを有効化し、不審なアクセスを検知できるようにする。
- バックアップやログの配置場所・権限を定期的に見直し、Web公開領域から完全に分離する。
7) 動的 include への警戒
- スクリプトを動的にロードする(
include/require等)処理は特に危険。 - 動的ロードが必要な場合は、必ず ホワイトリスト と パスの正規化 を組み合わせる。
- 可能であれば、動的ロード自体を排除し、ビルド時に依存関係を固定する設計に変更する。
- フレームワークのオートローダ機能を利用することで、安全な読み込み制御を実現できる。
まとめ
Directory Traversal(パストラバーサル)の脆弱性について、攻撃者の視点から具体的な手法と対策をかなり深いところまで学べました。 KENROでは、実際にCTF形式で脆弱性を試したり、コードの改修を通して学べるため、とても完成度の高い学習サイトでした!