15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【php】アップした画像をとことん調べる(画像アップロードにおけるセキュリティ対策)

Last updated at Posted at 2016-11-14

pngとjpegしか、アップさせないサーバ側のコードを書いてみました。

要は画像の拡張子と中身のチェック、トーコンチェック、画像を2変換して、リスクのあるコードを実行させないような処理。

Laravelを使ってるので、書き方が普通のPHPと少し違います。

//Fileの中身をチェックし、画像ファイルかどうかを検証する
if(count($_FILES) != 0)
{
    $file = request()->file('files')[0];

    $allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG);
    $detectedType = exif_imagetype($file);//普通のphp:exif_imagetype($_FILES['files']['tmp_name'][0]);

    $originalFileName = $file->getClientOriginalName();//普通のPHPだと:pathinfo($_FILES['files']['name'][0], PATHINFO_FILENAME);
    $extension = $file->getClientOriginalExtension();//普通のPHPだと:$array = explode('.', $_FILES['files']['name'][0]);$extension = end($array);

    if(!in_array($detectedType, $allowedTypes)) {
        header('Content-Type: application/json; charset=UTF-8');
        die(json_encode(array('message' => 'FormatErr')));
    } else {
        $regexPNG = '/png$/i';
        $regexJPG = '/jpe?g$/i';

        if((preg_match($regexPNG,$extension) && ($detectedType != 3)) || (preg_match($regexJPG,$extension) && ($detectedType != 2)))
        {
            header('Content-Type: application/json; charset=UTF-8');
            die(json_encode(array('message' => 'ExtensionErr')));
        }
        if (!preg_match('/\.(jpe?g|png)$/i', $_FILES['files']['name'][0])) {
            header('Content-Type: application/json; charset=UTF-8');
            die(json_encode(array('message' => 'ExtensionErr')));
        }

        // 画像アップロード・表示用のストレージ
        $imageFolder = ("abcde/");

        //重複しないファイル名を生成する
        $filename = $なんちゃらid . '_' . count($this->storage->files($imageFolder)) . '.' . $extension;//「storage」のはLaravelの書き方

        if (count(token_get_all($file)) >= 2)  {
            header('Content-Type: application/json; charset=UTF-8');
            die(json_encode(array('message' => 'ExtensionErr')));
        }

        //画像を二変換する 参考記事:https://blog.ohgaki.net/c_ra_a_a_ia_ca_la_lphpa_sa_fa_a_a_a_effa
        if (preg_match($regexPNG,$extension)) {

            //一回目
            $imageTmp1 = imagecreatefrompng($file);
            ob_start();
            imagejpeg($imageTmp1);
            $outputImage1 = ob_get_clean();
            imagedestroy($imageTmp1);

            //二回目
            $imageTmp2 = imagecreatefromstring($outputImage1);
            ob_start();
            imagepng($imageTmp2);
            $outputFinal = ob_get_clean();
            \Storage::put($imageFolder. $filename, $outputFinal);//Laravelの書き方

            //imagepng($imageTmp2, imageFolder. $filename, 0);//普通のPHPの書き方、直接ファイル出力したいところに置く。

            imagedestroy($imageTmp2);

        } else if (preg_match($regexJPG,$extension)) {//省略

        }

        //正常アップロード
                return response()->json(array());//普通のPHP:header('Content-Type: application/json; charset=UTF-8');echo json_encode(array());
        
    }
}
15
13
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?