概要
FTPサーバーにフォルダをアップロードする機能を実装しました。
複数のファイルを扱うため実装にwebkitdirectory属性を使用しましたが、公式で以下のような警告を見つけたので、この内容について深掘ってみました。
警告文
警告
webkitdirectory 属性は標準ではありませんし、 標準化の過程にも入っていません。
この属性を Web 上の本番環境で使わないで下さい: なぜなら、この属性を全ユーザーが使えるとは限らないからです。
また、この属性はクライアントの実装に非互換がある可能性もありますし、 振る舞いが将来変更される可能性もあります。
主な理由としてはwebkitdirectory属性はブラウザに依存するので、ユーザーによっては期待通りに機能しない可能性があるためのようです。
続いて、
PHP は ブラウザ/ユーザーエージェントから送られてきた相対パスの情報をパースし、 その情報を $_FILES 配列に渡すことだけを行います。
full_path 配列中の値が、 実際のディレクトリ構造を含んでいるという保証はありません。
よって、PHP アプリケーションはこの情報を信用してはいけません。
この箇所に触れる前に$_FIELSについて調べました。$_FILESはPHPで使用できるグローバルな変数で、フォームから送信されるファイルデータはこの変数に配列として格納されます。
この$_FILESのデータ構造内で、full_pathは以下の通りです。
["full_path"]=> array(2) { [0]=> string(15) "test1/.DS_Store" [1]=> string(16) "test1/hellow.pdf" }
PHPはユーザーが送信したデータをチェックしないため、場合によっては意図しないファイルが書き込まれてしまうリスクがあるということでした。
確かに、'../../'などと入っていたらファイルを遡られてしまいますし、'/'と頭についていたらルートに書き込むことも可能です。
警告文(別記事)
別の記事も読み、意図しない挙動について'Path Traversal'と命名されていることがわかりました。
The full_path array in each $_FILES field is not safe, because it is direct user input.
All values from this array must be validated to prevent potential vulnerabilities,
especially when storing the uploaded files in sub directories on the server.
対応
このリスクの対応についてその一部をご紹介します。
.. が含まれていないか(意図しないディレクトリの移動)
絶対パスではないか
使用できる文字だけか
想定したディレクトリ配下だけになるか
公式に'この属性を Web 上の本番環境で使わないで下さい'とあったことが深掘りするモチベーションになりました。リスクについて理解し、より安全性の高い設計に活かしたいと思います。
記事内容についてご指摘があればコメントをいただけますと幸いです☺️