ファイルのアップロード時に気を付ける点

PHP

A. 日本語がファイル名に含まれていないか?
B. ファイル名にA-Za-z_-. 以外の文字が含まれていないか?
C. POST時にエラーが発生していないか?
D. ファイル名が空でないか?
E. 不正なパスを表す文字列がファイル名に含まれていないか?( /  や ../ など )
F. ファイルサイズが0バイトより大きく指定値以内か?
G. 本当にアップロードされたファイルなのか?(is_uploaded_file()で確認します)
H. 既存ファイルが存在していないか?(削除して上書きする、またはエラーとするか?)

上記は、https://teratail.com/questions/30411 より転記。

 

その他、

I. ファイル名をハッシュ化して移動・保存。(move_uploaded_fileを使うタイミングで)
J. png,jpg,pdfなど拡張子を制限する。
K. SWFファイルの制限。
L. 保存フォルダを公開ディレクトリから外す(アクセスし、phpなどが実行されたくないためであり、読み込みはreadfileを使う)
M.

 

<?php

$maxsize = $_POST["MAX_FILE_SIZE"];

$extension = array("image/jpeg", "image/png", "application/pdf");

$ds = DIRECTORY_SEPARATOR;

$storeFolder = "temp_dir";	//同じディレクトリ内にある一時保存用ディレクトリ

$DirPath = dirname( __FILE__ ).$ds.$storeFolder.$ds;

$CookieData = $_COOKIE["CookieData"];	//事前にユーザ毎に付与しているランダムな文字列


//[アップロード]ボタンの押下確認
if (isset($_POST["upload"])) {


	foreach($_FILES["upfile"]["tmp_name"] as $no => $tmp_name){

	    //エラーはないか?
	    if(!empty($_FILES["upfile"]["name"][$no]) && empty( $_FILES["upfile"]["error"][$no])){

		//サイズは超えていないか?
		if(($_FILES["upfile"]["size"][$no] > 0) && ($_FILES["upfile"]["size"][$no] < $maxsize)){

		    //アップロードされたファイルか?
		    if(is_uploaded_file($_FILES["upfile"]["tmp_name"][$no])){

			//拡張子を判定する
			$type = mime_content_type($_FILES["upfile"]["tmp_name"][$no]);
			if(in_array($type, $extension)){


				//一時保管されているファイル名
				$tempFile = $_FILES["upfile"]["tmp_name"][$no];

				//アップロードされたファイル名
				$filename = $_FILES["upfile"]["name"][$no];

				$file = explode(".", $filename);
				$ext = array_pop($file);

				//md5でハッシュ化。別のユーザーと同名のファイル名であったとしても被らないよう、
				//事前にユーザ別にランダムな文字列をcookieに持たせており、その値をファイル名へ。
				//また、ファイル数に応じて、番号も付与。
				//ファイル名を取得する際、basename()を用いることでファイルシステムトラバーサル攻撃は防げる
				//とのことだが、ハッシュ化すればその対策は必要ないのだろうか??

				$new_filename = $CookieData."-".$no.md5($filename).".".$ext;

				//設定するファイル
				$targetFile = $DirPath.$new_filename;

				//一時保管用にハッシュ化したファイルをセット
				if(move_uploaded_file($tempFile,$targetFile)){


					//*** 画像ファイルだったらサイズ変更 ***
					if($type != "application/pdf"){	

						$upfile = $storeFolder."/".$new_filename;

						list($width, $height, $mime_type) = getimagesize($upfile);


						if($width > 1000){	//1000pxを超えるとき


							$hiritsu = 1000 / $width;

							$width_edit = floor($width * $hiritsu);
							$height_edit = floor($height * $hiritsu);


							switch($mime_type){

							    //jpegの場合
							    case IMAGETYPE_JPEG:
								$src = imagecreatefromjpeg($upfile);
							        break;

							    //pngの場合
							    case IMAGETYPE_PNG:
							    //拡張子の設定
								$src = imagecreatefrompng($upfile);
							        break;

							}

							$dst = imagecreatetruecolor($width_edit, $height_edit);

							imagecopyresampled($dst, $src, 0, 0, 0, 0, $width_edit, $height_edit, $width, $height);

							imagejpeg($dst, $upfile);

						}

					}//**********************


			   		 $error .= $no."成功です。<br />";

				}
				else{
			   		 $error .= $no."失敗です。<br />";
				}
			}
			else{
			    $error .= $no."この拡張子は利用できません。<br />";
			}
		    }
		    else{
			$error .= $no."ファイルがアップロードされていません。<br />";
		   }
		}
		else{
		    $error .= $no."ファイルサイズが指定サイズを超えています。<br />";
		}
	    }
	    else{
		$error .= $no."ファイルアップロードエラーです。<br />";
	    }
	}
}


?>



<html lang="ja">
<head>
<meta charset="utf-8">
<script>
<!--
//アップロードを許可する拡張子
var allow_exts = new Array('jpg', 'jpeg', 'png', 'pdf');

//フォーム内容の確認をする関数
function checkForm()
{
	var files = document.getElementsByName('upfile[]')[0].files;
	//ファイルが選択されているか確認
	if (files.length == 0) {
		alert('ファイルを選択してください');
		return false;
	}
	//指定されたファイルの数だけ拡張子をチェックする
	for (var i = 0; i < files.length; i++) {
		if (!checkExt(files[i].name)) {
			alert(files[i].name+'はアップロードできません');
			return false;
		}
	}
	//チェックを通ったらtrueを返す
	return true;
}

//アップロード予定のファイル名の拡張子が許可されているか確認する関数
function checkExt(filename)
{
	//比較のため小文字にする
	var ext = getExt(filename).toLowerCase();
	//許可する拡張子の一覧(allow_exts)から対象の拡張子があるか確認する
	if (allow_exts.indexOf(ext) === -1) return false;
	return true;
}

//ファイル名から拡張子を取得する関数
function getExt(filename)
{
	var pos = filename.lastIndexOf('.');
	if (pos === -1) return '';
	return filename.slice(pos + 1);
}
-->
</script>
</head>
<body>

<h1>アップロード処理</h1>

<?php echo $error; ?>

<form action="./" enctype="multipart/form-data" method="post" onsubmit="return checkForm();">
<input type="hidden" name="MAX_FILE_SIZE" value="5097152">
<input type="file" name="upfile[]" accept=".jpg,.png,image/jpeg,image/png,application/pdf" /><br />
<input type="file" name="upfile[]" accept=".jpg,.png,image/jpeg,image/png,application/pdf" /><br />
<input type="file" name="upfile[]" accept=".jpg,.png,image/jpeg,image/png,application/pdf" /><br />
<input type="submit" name="upload" value="アップロード">
</form>




</body>
</html>

 

コメント

タイトルとURLをコピーしました