PHPで画像XSSの一味変わった対策。

IE仕様?をついた画像ファイルを使用したXSSというのがあります。なかなか決定的な対策がなく、私も困っています。画像の再コンバートとか、画像のファイルヘッダを確認するのも。コメントとかカラーパレットとかで、決定的なものがありません。

が、ちょっと作ってみたのが、
1.空の画像を作って
2.ユーザのアップロードしてきた画像を空の画像にコピーする

これだといけそうな気がしたので作っていました。

PHPのimagecopyを使って画像XSSをやっつける。どうぞHACKしてください。

http://tepppei.com/hackme/img.php






画像XSSの詳しくは有名な方々のブログの方にお任せ。

<html>
画像XSSの対策をしました。<br>
任意の画像ファイルをアップロードしてください。<br>
完了したら対策した画像のリンクが出ます。<br>
XSSが動いたらおめでとうですね。連絡ください。cybert.jp@gmail.com<br>
<form  action="img.php" method="post" enctype="multipart/form-data">
<input type="file" name="userfile">
<input type="submit" name="submit" value="送信">
</form>
<?
if(!$_FILES['userfile']['name']){
	die();
}
$user_filename = $_FILES['userfile']['name'];
$user_file = $_FILES['userfile']['tmp_name'];

//画像ファイルの高さ、幅のサイズ取得を試みる
list($width, $height) = getimagesize($user_file);
if(0 < $width + $height){} else {die("エラー:SIZEエラー");}

//拡張子を調べる
if(preg_match("/^.+\.jpeg$/i",$user_filename) OR preg_match("/.+\.jpg$/i",$user_filename)){
	$ftype = "JPG";
}elseif(preg_match("/^.+\.png$/i",$user_filename)){
	$ftype = "PNG";
}elseif(preg_match("/^.+\.bmp$/i",$user_filename)){
	$ftype = "BMP";
}elseif(preg_match("/^.+\.gif$/i",$user_filename)){
	$ftype = "GIF";
}else{
	die("エラー:サポートしてません");
}

//空の画像を作ります
$blank_img = imagecreatetruecolor($width + 1,$height + 1);

//イメージIDをGETします
switch ($ftype) {
    case "JPG":
		$user_img  = imagecreatefromjpeg($user_file);
        break;
    case "PNG":
        $user_img  = imagecreatefrompng($user_file);
        break;
    case "BMP":
        $user_img  = imagecreatefromwbmp($user_file);
        break;
    case "GIF":
        $user_img  = imagecreatefromgif($user_file);
        break;
    default:
    	die("エラー");
}

//ここがポイント。空の画像に、ユーザの画像をコピーします。
imagecopy($blank_img,$user_img,0,0,0,0,$width + 1,$height + 1);


//コピーした画像を上書きします
switch ($ftype) {
    case "JPG":
		imagejpeg($user_img,$user_file);
        break;
    case "PNG":
        imagepng($user_img,$user_file);
        break;
    case "BMP":
        imagewbmp($user_img,$user_file);
        break;
    case "GIF":
        imagegif($user_img,$user_file);
        break;
    default:
    	die("エラー");
}

//メモリ上の画像を破棄します
imagedestroy($blank_img);
imagedestroy($user_img);

$fname = time() . "." . $ftype;
move_uploaded_file($_FILES['userfile']['tmp_name'], dirname(__FILE__)  . "/". $fname );

print "<a href=\"{$fname}\">アップロード完了</a>";