見えるセキュリティ

ディレクトリトラバーサル(パストラバーサル)

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: ファイル指定をサーバーへ送る

現在のSTEP 1STEP 2STEP 3STEP 4

利用者がfileに「../private/memo.txt」を指定します。取得機能が想定する範囲は「/srv/app/files」で、通常の取得対象はその中のguide.txtです。

技術的な詳細を見る

要求先はhttps://files.example/download。図で追うのは、通常のパラメータ解析後のfileの値です。URLのパス自体を操作する例ではありません。[T01・T02]

パネルの開閉ではSTEPは変わりません。

この概念の要点

  • 要点

    外部入力で、対象範囲の外を指せることがある

    ../ や絶対パスなどをファイル指定に利用できると、想定したフォルダーの外へ参照先を変えられることがあります。固定のフォルダーを前置するだけでは不十分です。[T01・T02]

  • 要点

    正規化と、読んでよい範囲の確認は別

    パスを整理しても、その場所が公開対象とは限りません。主図では、開発者が決めた基準の階層と解決後の参照先をサーバーが比較し、filesとprivateの不一致を理由に読み取り前に拒否します。[T02・T05]

  • 要点

    指定方法を限定し、認可と最小権限も確認する

    可能なら固定IDからサーバー側のファイルを選びます。その利用者が読んでよいか、アプリに不要なOS権限がないかも別に確認します。[T01・T02・T03・T04]

理解確認

主図で両モードの解決先は同じです。「範囲確認あり」でメモ本文が返らない理由はどれですか?

理解確認

対象範囲は /srv/app/files です。整理した参照先が /srv/app/files-backup/memo.txt のとき、正しい説明はどれですか?

理解確認

ダウンロード対象がサーバーで管理する数件だけなら、適切な設計はどれですか?

ディレクトリトラバーサル(パストラバーサル)の補足

..、正規化、フォルダーの境界

この例で .. は親フォルダーを指します。基準に /srv/app/files を付けても、/srv/app/files/../private/memo.txt を整理すると /srv/app/private/memo.txt になります。文字列上で .. がなくなったことは、対象フォルダーの内側になったことを意味しません。[T02・T05]

/srv/app/files との関係
整理した参照先対象範囲との関係
/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]

参考資料