PortSwigger-PathTraversal

パストラバーサルを実行するときに覚えておきたい事項として、ブラウザを利用してパストラバーサルを行うのは面倒くさいということです。
パスの正規化がRFC上、MUSTだった記憶があるため、../../とつけていると、それらは削除してブラウザがデータを送信します。
そのため、ローカルプロキシ経由で通信を改ざんして送りつける方が楽です。
ブラウザでデータを送信するには、以下のようにパーセントエンコーディングした文字列にして送りつけるくらいかと思います。
. (ピリオド) = %2E
/ (スラッシュ) = %2F
Lab: File path traversal, simple case
image取得のクエリ名にディレクトリトラバーサルの脆弱性があります。
/image?filename=../../../../../../../../etc/passwd
これでリクエストを送るだけだと、レスポンスの内容を表示できません。
ServerのContent-Typeがimage/jpegであるためです。
BurpSuiteを使うと、レスポンスを生データとして表示できるため、レスポンスをRawで表示すると中身が見れます。
File path traversal, traversal sequences blocked with absolute path bypass
イメージ取得のクエリ名にディレクトリトラバーサルの脆弱性があります。
パストラバーサルシーケンス(../../)はチェックされているため、画像の絶対パスとして/etc/passwodを指定すれば成功します。
File path traversal, traversal sequences stripped non-recursively
ディレクトリトラバーサルを防ぐ方法として、../ を削除するようなプログラムが考えられます。
これを実現するには、再帰的に文字列を評価し続けなければいけませんが、行われない問題だとわかります。
最もシンプルな解法だと以下のリクエストを含める方法になりそうです。
….//….//….//….//….//etc/passwd
../を削除していくと、ディレクトリトラバーサルの文字列になることがわかります。
以下のようなパターンでも通過しました。
…/./…/./…/./…/./…/./etc/passwd
File path traversal, traversal sequences stripped with superfluous URL-decode
タイトルの訳し方が難しいのですが、「過剰なURLデコードにより、本来無効化されたパストラバーサル用の文字列(../
など)が復活し、パストラバーサルが成立してしまう脆弱性」という意味になります。
サーバ側でURLデコードを何度も行うと、それに伴って、URLエンコードを複数回行われる脆弱性が生まれます。
以下のようにすれば、回避できます。
..%252F..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd
File path traversal, validation of start of path
/image?filename=/var/www/images/5.jpg
クエリ文字の指定方法が/var/www/images/から始まることを期待しているため、../../などを入れるとディレクトリトラバーサルが成功します。
/var/www/images/../../../../etc/passwd
File path traversal, validation of file extension with null byte bypass
ファイルの拡張子をチェックして、アクセスしているファイルを表示するロジックがあるはずです。
PHPの古いバージョンでの文字比較用の関数で、null文字を終端文字と判断してしまいます。
$filename = $_GET['filename']; // クエリ文字列から取得
if (endsWith($filename, ".png")) {
$path = "/var/www/images/" . $filename;
echo file_get_contents($path);
}
ChatGPTに脆弱性が生まれるコード例を作ってもらいましたが、末尾からマッチングするときにもnullによって精査が終了し、アクセス先のファイル指定時にもnullによって精査が終了します。
よくできてるなと感じます。
../../../../../../../etc/passwd%00.png