概要:
多くのWebシステムにおいてファイルダウンロード機能が実装されている。通常、ダウンロードリンクをクリックするとバックエンドにダウンロード要求が送信され、その要求にはダウンロード対象のファイル名が含まれる。バックエンドはこのファイル名を受け取り、対応するファイルをブラウザにレスポンスしてダウンロードを完了させる。しかし、バックエンド側で受け取ったファイル名をセキュリティチェックなしにパス構築に使用してしまうと、安全でないファイルダウンロードの脆弱性が生じることがある。
攻撃者が意図しないファイル名を送信し、例えば "../../../etc/passwd" のようなパスを指定した場合、予期せぬファイルがダウンロードされる可能性がある。これにより、システムの機密情報(パスワードファイルやソースコードなど)が漏洩するリスクがある。したがって、ファイルダウンロード機能を設計する際には、フロントエンドから渡されるファイル名について適切なセキュリティ対策を行う必要がある。
重要なことだが、すべてのフロントエンドとの通信データは信頼できないものとして扱うべきである。
テスト環境:
- テスト環境にアクセスし、ユーザー名をクリックするとダウンロードダイアログが表示される。
ダウンロードURLは以下の通り:
http://localhost/pikachu/vul/unsafedownload/execdownload.php?filename=kb.png
-
フロントエンドからバックエンドへファイル名が渡され、バックエンドは ai.png ファイルを検索してフロントエンドに返却し、ユーザーはファイルをダウンロードできる。
-
filenameパラメータを変更してファイルパスを指定すると、hostsファイルの内容を取得できる。
../../../../../../../../../../Windows/System32/drivers/etc/hosts
- ソースコードを確認する。
バックエンドコードの解析と脆弱性の原因:
ページ上のリンクをクリックすると、aタグがGETリクエストでパラメータをバックエンドに送信する。バックエンドではこのパラメータに対する処理が一切行われず、そのままファイル名をダウンロードディレクトリに結合してファイルを読み取っている。その後、ファイルサイズを計算し、HTTPヘッダーに設定して、ファイルのバイト列をループで読み取りながらフロントエンドに返す。根本的な問題は、受け取ったパラメータがディレクトリ内のファイルかどうかを検証せずに直接ファイルを読み込んでしまっていることである。