Mediaプラグインをアップロード処理の基本から学ぶ(2) - 制限, 検証

検証環境

PHPのアップロード処理

PHPのアップロードサポートでは、基本的にアップロードされたファイルの以下の情報が$_FILES*1連想配列として入ります。*2

  1. name - アップロード元のファイル名
  2. type - MIMEタイプ
  3. size - ファイル容量(バイト)
  4. tmp_name - 一時ファイルとして保存されたアップロードファイルのパス
  5. error - アップロードに成功したか(エラー内容)

これらを元に、ファイルの検証・移動を行います。

1. name - アップロード元のファイル名

送信元から送られてくるファイル名が入りますが、これはあまり信用してはいけません
悪意のあるファイル名の送信により、プログラム上で対策を行わないと上位ディレクトリのファイルにアクセスされる危険性もあります。
また、ファイル名がマルチバイトである場合、ファイルシステムによってはアクセスが不可能であるかまたは困難となる可能性があります。
これを回避するために、Transferビヘイビアのtransfer()メソッドを、モデルが同名のメソッドを実装することによりオーバーライドする必要があります。
具体的な実装に関しては、docs/TUTORIAL at from davidpersson/media - GitHubを参考にしてください。

2. type - MIMEタイプ

MIMEタイプが入りますが、マニュアルにもある通り、送信側から送られてきたヘッダーの内容がそのまま入るので、これは信用できません
Mediaプラグインは、上述のmmライブラリを使ってMIMEタイプを自動解析します。
MIMEタイプの解析の方法は様々ありますが、例えばFileInfoなどを使って解析することができます。
これはmmのMime_Typeの設定で変更することができます。


また、解析済のMIMEタイプを用いて、checkMimeType*3バリデーションが使用できます。

3. size - ファイル容量(バイト)

ファイルのバイト数が入ります。
PHPの設定によりファイルサイズも制御できますが、アップロードされるファイルの種類によってファイル容量を抑制する場合は、アプリケーション側で処理をする必要が出てきます。
これをMediaプラグインcheckSizeバリデーションで行います。

4. tmp_name - 一時ファイルとして保存されたアップロードファイルのパス

アップロードされたファイルは、一時的なファイルとしてファイルシステムに保存されます。(/tmpや、C:\TEMPなど)
これをPHPアプリケーションが取り扱えるディレクトリにコピー、または移動する*4ことによって、アプリケーションがはじめてそれを単純なファイル
として操作
することが可能になります。
なお、移動先はMediaプラグイン設定のtransferになります。(後の記事で説明)

5. error - アップロードに成功したか(エラー内容)

PHPのエラー定数を用いて判別しますが、要は

  • ファイルがアップロードされていないか
  • アップロードされたファイルが壊れていないか
  • PHPなどの設定上の制限を満たしているか
  • その他システムエラーが起きているか

などの場合分けです。
アップロードされていない、もしくは正しくアップロードが完了していない場合、Mediaプラグインはこれを無視します

ファイルの移動

ファイルの移動を行う時に、その移動元、移動先が正しい場所であるか検証する必要があります。

ファイルの場所

もしシステムファイルにアクセスできたり、または特定のディレクトリにアップロードファイルが書き込まれることがあったら、非常に危険な事態に陥る可能性があります。
これを検証するために、MeidaプラグインcheckLocationバリデーションが利用できます。例えば、/tmpAPP/tmpAPP/webroot/mediaMEDIA定数)等を指定します。

ファイルのアクセス権限(パーミッション

移動元のファイルは読み込み可能であり、移動先のディレクトリは書き込み可能である必要があります。
そうでない場合、アップロードが必ず失敗することは想像の範疇だと思います。
これは、MediaプラグインcheckAccessバリデーションを使用することで検証できます。


また、移動元のファイルにもし実行可能属性が付いていたらどうでしょうか。
そうなる状況はあり得るかという疑問はありますが、実際共有サーバーなどで/tmpなどに悪意のある操作をされることは想定できます。
これを検証するために、MediaプラグインにはcheckPermissionバリデーションが用意されています。

その他の制限、検証

拡張子

拡張子そのものを制限します。これはMIMEタイプでapplication/octet-streamを許可した場合など、与えられた拡張子がアプリケーションの要件にあったものかを制限します。
これはcheckExtensionバリデーションがMediaプラグインに用意されています。

ピクセル

ピクセル数を制限します。
ピクセル数が大きい物をリサイズする時に、メモリを非常に多く浪費します。
これを制限しないと、PHP、またはサーバーのメモリ限界を超えることになり、最悪ハングアップすることもあります。
また、このチェックではMediaプラグインcheckPixelsバリデーションが利用できます。

次回予告

いかがだったでしょうか。アップロードの検証だけでも多くの面からの処理が必要になることが理解できると思います。
次回はアップロードされたファイルの変換と配置についてになります。
サムネイルの生成など、アプリケーションのロジックにも関わるところで、一番関心を引くところではないでしょうか。

次回: Mediaプラグインをアップロード処理の基本から学ぶ(3) - 変換, 配置 -

*1:CakePHPでは、FormHelper#file()などで出力したinput[type=file]の内容は、$_FILESからディスパッチャを通して$this->dataに格納されます。

*2:PHP: POST メソッドによるアップロード - Manual

*3:この記事で**バリデーションと表記しているものはTransferビヘイビアのものを指す

*4:PHP: move_uploaded_file - Manual