制限のないファイルアップロード

制限のないファイルアップロード

説明

アップロードされたファイルの名前、拡張子、MIMEタイプ、保存先を検証しないと、実行可能なファイルや危険な内容を保存されるおそれがあります。

想定される影響

Webシェルのアップロード、悪意あるファイルの配布、既存ファイルの上書きにつながる可能性があります。

対処方法

サーバーが生成したファイル名を使い、拡張子とMIMEタイプを許可リストで検証します。アップロード先ではファイルを実行できないようにします。

例

変更前

php
<?php
$target = 'uploads/' . basename($_FILES['uploaded']['name']);
move_uploaded_file($_FILES['uploaded']['tmp_name'], $target);

変更後

php
<?php
if ($_FILES['uploaded']['error'] === UPLOAD_ERR_OK
    && mime_content_type($_FILES['uploaded']['tmp_name']) === 'image/png') {
    $target = '/var/app/uploads/' . bin2hex(random_bytes(16)) . '.png';
    move_uploaded_file($_FILES['uploaded']['tmp_name'], $target);
}

解説:

  • 変更前: 種類、拡張子、保存先を検証せずに、クライアントが指定したファイル名を使っています。
  • 変更後: アップロードの状態と内容の種類を確認し、サーバーが生成した名前で、実行されない場所に保存します。

これはアップロード処理の一部です。実際のサービスでは、サイズを制限し、許可した形式の内容を検証して、保存の失敗も処理してください。/var/app/uploads/ のファイルをWebサーバーが実行できないよう、別途設定する必要があります。

参考資料