見えるセキュリティ
ディレクトリトラバーサル(パストラバーサル)
PATH TRAVERSAL
この概念とは?
ディレクトリトラバーサル(パストラバーサル)は、外部入力から作るファイルのパスを適切に制限できず、想定したフォルダーの外を参照できてしまう問題です。たとえば ../ を含む入力は、親フォルダーを経由して別の場所を指すことがあります。サーバーがその参照先を確認せず読み取って返すと、公開を想定しないファイルの内容が漏れる恐れがあります。[T01・T02]
公開対象フォルダーを指定したのに、なぜ外のファイルを読まれてしまうのか?
- THEME
- web-vuln
- KIND
- attack
- REVIEW
- self-reviewed ·
パスは、ファイルの場所を表す文字列です。この図では / でフォルダーを区切り、.. は一つ上のフォルダーを指します。同じ入力から同じ参照先を求め、読み取り前の範囲確認だけを切り替えます。
架空のフォルダーと教材用データを使った図解です。実際のファイルアクセスや外部通信は行いません。
利用者が指定:file=../private/memo.txt
サーバー側アプリの中
受け取ったfileの値(両モード共通)
../private/memo.txt
サーバー内の仮想フォルダー
一つ上のフォルダー
/srv/appこの機能の対象範囲
files
guide.txt通常の取得対象対象範囲の外
private
memo.txt非公開メモ緑の枠が対象範囲です。filesとprivateは、同じ親を持つ隣のフォルダーです。
ファイルの本文は まだ読み取っていません
メモ:未読取 / 応答前
両モードとも、同じ入力・フォルダー・OS読み取り権限です。変わるのは、サーバーが読み取り前に範囲確認するかどうかだけです。
詳しく見る:パスと主図の前提
- 要求先
https://files.example/download- 基準フォルダー
/srv/app/files- 組み立てたパス
まだ組み立てていません- 整理した参照先
未確定
通常の指定例:file=guide.txt は対象範囲内の /srv/app/files/guide.txt を参照します。主図の入力は変えていません。
両モードとも、アプリにメモのOS読み取り権限あり。固定のPOSIX風階層で、ファイルは存在します。リンク・マウントによる別名・差し替え・同時変更はありません。privateという名前自体に、OSの特別な防御機能はありません。
正規化は参照先の整理であり、安全なフォルダーへ戻す修復ではありません。主図の200/403は、この例で選んだステータスです。サーバー内の説明と利用者への応答は別で、拒否応答に内部パスやメモ本文を含めません。
HTTP要求の表記を見る
GET /download?file=..%2Fprivate%2Fmemo.txt HTTP/1.1 Host: files.example
利用者が指定したパスをサーバーへ送ります。整理した参照先は未確定。範囲確認は未到達。メモは未読取。応答は応答前です。ファイルは元の場所に残ります。
入力へ基準フォルダーを付け、パスを整理するだけでは、対象範囲の外を指すことがあります。この例では、サーバーが範囲外と分かった時点で読み取りを拒否すると、メモの本文は返されません。可能なら外部入力でパスを直接指定させず、サーバー側で選べるファイルを限定します。[T01・T02・T03]
STEP 01 / 4
ファイル指定をサーバーへ送る
STEP 1 / 4: ファイル指定をサーバーへ送る
利用者がfileに「../private/memo.txt」を指定します。取得機能が想定する範囲は「/srv/app/files」で、通常の取得対象はその中のguide.txtです。
技術的な詳細を見る
要求先はhttps://files.example/download。図で追うのは、通常のパラメータ解析後のfileの値です。URLのパス自体を操作する例ではありません。[T01・T02]
この概念の要点
要点
外部入力で、対象範囲の外を指せることがある
../ や絶対パスなどをファイル指定に利用できると、想定したフォルダーの外へ参照先を変えられることがあります。固定のフォルダーを前置するだけでは不十分です。[T01・T02]
要点
正規化と、読んでよい範囲の確認は別
パスを整理しても、その場所が公開対象とは限りません。主図では、開発者が決めた基準の階層と解決後の参照先をサーバーが比較し、filesとprivateの不一致を理由に読み取り前に拒否します。[T02・T05]
要点
指定方法を限定し、認可と最小権限も確認する
可能なら固定IDからサーバー側のファイルを選びます。その利用者が読んでよいか、アプリに不要なOS権限がないかも別に確認します。[T01・T02・T03・T04]
理解確認
理解確認
理解確認
ディレクトリトラバーサル(パストラバーサル)の補足
..、正規化、フォルダーの境界
この例で .. は親フォルダーを指します。基準に /srv/app/files を付けても、/srv/app/files/../private/memo.txt を整理すると /srv/app/private/memo.txt になります。文字列上で .. がなくなったことは、対象フォルダーの内側になったことを意味しません。[T02・T05]
| 整理した参照先 | 対象範囲との関係 |
|---|---|
| /srv/app/files/guide.txt | 対象範囲の内側 |
| /srv/app/private/memo.txt | 親を共有する別フォルダー。範囲外 |
| /srv/app/files-backup/memo.txt | 名前の先頭が似ている別フォルダー。範囲外 |
未解決パスや、区切りを考慮しない単純なprefix一致だけでは不十分です。/srv/app/files-backup は /srv/app/files の子フォルダーではありません。先頭一致を使うあらゆる手法が一律に誤り、という意味ではありません。[T02・T05]
公開対象フォルダーは、この機能で返してよいと設計した範囲であり、Webサーバーのdocument rootと同じである必要はありません。
基準の /srv/app/files は、開発者が決めてサーバー側へ設定します。利用者が送った値で基準を変更したり、ファイル自体に「範囲外」という属性を付けたりする仕組みではありません。主図では、サーバー側アプリが基準の srv・app・files と参照先の srv・app・private を比べ、3番目の不一致から範囲外と判定します。[T02・T05]
基準の全要素が先頭から一致し、その下の対象を指す場合だけ読取側へ進みます。guide.txtなら3要素が一致し、その下のファイルを指すので範囲内です。files-backupはfilesと異なる要素です。基準フォルダーそのものや、それより上も、このファイル取得機能では拒否します。範囲内かの判定と、存在・通常ファイルか・OS権限・利用者への認可の確認は別です。[T02・T05]
固定IDからサーバー側でファイルを選ぶ
取得対象を限定できるなら、利用者から自由なパスを受け取らず、固定IDから既知のファイルを選ぶ設計を優先します。登録していないIDは拒否します。[T01 3-(i)-a・T02・T03]
- guide
- 既知の /srv/app/files/guide.txt
- 未登録のID
- ファイルを選ばず拒否
この対応表はサーバー側で管理します。利用者が送るhidden項目や、画面上の選択肢だけで制限したことにはなりません。ID化しても、その利用者が対象ファイルを読んでよいかの認可は別に必要です。[T02・T04]
OS・デコード・リンクも考える
実際のパスの解釈はOSやAPIで違います。絶対パス、Windowsの区切り、URLエンコード等もあるので、文字列の ../ を探して削除するだけでは十分とは限りません。受信からパスの利用まで、デコードと検証の順序を整理し、検証後に再び意味が変わる処理を入れないようにします。[T01 3-(iii)・T02・T03]
正規化は、文字列上の整理だけを行うAPIと、実際のシンボリックリンク(別の場所を指すリンク)等を解決するAPIを区別します。たとえばNodeのpathによる整理と、fs.realpathによる実際の参照先の解決は役割が異なります。[T05・T06]
さらに、確認した後にファイルやリンクを差し替えられる環境では、確認時と読み取り時で対象が変わる問題もあります。realpathを呼んでから範囲を調べれば、どんな環境でも保証できる、とは限りません。実環境のファイル操作・権限・変更できる主体に合った対策が必要です。[T07]
最小権限・認可・応答の扱い
この攻撃で読み取れる範囲は、アプリのプロセスが持つ権限等にも制約されます。アプリに不要な読み取り・書き込み権限を与えないことは、被害を抑える対策になります。主図ではアプリが読める前提なので、アプリ側の範囲確認の有無が結果を変えています。[T01 3-(ii)・T02]
ディレクトリトラバーサルは読み取りだけに限りません。機能と権限によっては、範囲外ファイルの書き込みや削除などにつながる場合もあります。この教材は、ファイルを読み取り本文として返す場面に絞っています。[T01・T02]
アプリがOS上で読めることと、その利用者へ返してよいことは別です。対象フォルダーの中でも、他人のファイルを返してよいわけではありません。範囲確認と、利用者ごとの認可を区別します。また、拒否応答に内部パスや詳細なエラーを出さず、応答を通じた情報の漏れを抑えます。[T02・T04]
参考資料
- IPAIPA — 安全なウェブサイトの作り方:1.3 パス名パラメータの未チェック/ディレクトリ・トラバーサル
T01改訂第7版第4刷(2021-03-31)の該当資料|概要、3-(i)-a/b、3-(ii)/(iii)|設計・固定dirの限界・権限・デコード|確認:2026-10-17
- CWEMITRE — CWE-22: Improper Limitation of a Pathname to a Restricted Directory
T02CWE 4.20|Description、Extended Description、Common Consequences、Potential Mitigations、Demonstrative Examples|境界・固定ID・最小権限・エラー|確認:2026-10-17
- OWASPOWASP Community — Path Traversal
T03更新日不明|Overview、How to protect yourself|パス入力・許可値・OS権限|確認:2026-10-17
- OWASPOWASP — Authorization Cheat Sheet
T04設計指針|Validate the Permissions on Every Request、Ensure Lookup IDs…、Verify … Right Location|IDと認可・サーバー側の判断|確認:2026-10-17
- 参考資料Node.js — Path
T05閲覧版v26.12.0|normalize、resolve、relative、posix|文字列上の解決・階層|確認:2026-10-17
- 参考資料Node.js — File system: fs.realpath
T06閲覧版v24.22.0|fs.realpath|シンボリックリンク等の参照先解決と文字列処理の違い|確認:2026-10-17
- CWEMITRE — CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition
T07CWE 4.20|Description・確認と利用の間の状態変化|主図の前提と競合の限界|確認:2026-10-17