【php】【セキュリティ対策】getimagesize関数で防げない不正画像アップロード対策について
こんにちは、webエンジニアのゾノ( @ozonosho )です。
今回はphpによる画像アップロード時のバリデーションについてです。
アップロード機能は自社サーバー内にユーザーの所有するファイルをアップロードするため、とりわけセキュリティリスクの高い機能になります。
通常、画像アップロードにおいては下記のようなバリデーションをおこないます。
- 画像アップロードのバリデーション
-
- 画像形式チェック(拡張子やMIMEタイプに問題ないか)
- 容量チェック
- 権限チェック(適切な権限を持つユーザーかどうか)
しかし上記のバリデーションでは防げないケースがあります。
それは「スクリプトを埋め込んだテキストファイルの拡張子を.pngや.jpgにしてアップロードされる」というケースです。
この場合、拡張子チェックで弾けないのはもちろん、MIMEタイプもimage/gifとして認識されてしまい、exif_imagetype関数やmime_content_type関数やgetimagesize関数を利用してもエラー判定できません。
ちなみに、ググって出てくる記事のほとんどは上記関数を利用したバリデーションまでしか記載されていません。
ではこういったケースでどうすれば良いかというと、下記2つの方法があります。
(他にもあるかもしれません)
- 本当に画像ファイルなのか判定する方法
-
- アップロードファイルのマジックナンバーを見る
- アップロードファイルの中身のバイナリデータから画像を生成できるか確かめる
①のマジックナンバーとはファイルごとのフォーマットを識別するための特定の数値のことで、アップロードファイル内にこの数値が含まれているかどうかでバリデーションする方法です。
ただ、、、テストした限り①だと完璧に弾くことはできなかったので僕は②を採用しました。
②はアップロードされたファイルの中身を読み込んで画像として正しく生成できるかチェックする方法です。
phpの「imagecreatefromstring」という関数を利用することで実装できます。
※imagecreatefromstring関数の詳細はphp.net参照
この方法だと画像のフリをした怪しいファイルをほぼ弾くことができるので、画像アップロード機能を実装する際にはぜひ利用してみてください。
おわりに
以上、今回の記事ではphpによる画像アップロード時のバリデーションについて紹介させていただきました。
当サイトではWordPressのカスタマイズ依頼を請け負っています。実現したい機能・要望がある方はぜひ下記ページよりご相談ください。