前段時間,公司幾年前開發的站點受到了攻擊,不是SQL注入的攻擊,而是aspxspy的攻擊,這是一個ASP的頁面,以運行CmdShell的方式來獲取服務器的信息,但是以後綴名爲jpg的文件保存,將其僞裝成圖片上傳至服務器,然後就開始讀取服務器上的所有信息,如果在開發的時候就對服務器上各個文件夾的權限做了詳細的設置的話,這個程序倒是沒有權限去更改服務器上的文件,但是發生這種情況最根本的源頭就是未對上傳的文件類型做判斷,不是簡單的去判斷文件的後綴名,而是進一步的判斷某一文件是否爲允許上傳的文件類型,具體針對圖片的判斷其實很簡單,用下面的代碼就可以簡單解決:
private bool IsImage(string filePath)
{
Image image;
try
{
image = Image.FromFile(filePath);
image.Dispose();
return true;
}
catch (Exception ex)
{
return false;
}
}
PHP 圖片上傳,如果不做任何判斷的話,隨便一個文件如 rar,zip,php,java等文件改個文件名,改個後綴就能以圖片形式上傳的服務器,往往會造成極大的危害!
第一種方法:如果是隻是單純判斷是否是圖片格式的話,我使用 getimagesize 方法
function checkIsImage($filename){
$alltypes = '.gif|.jpeg|.png|.bmp';//定義檢查的圖片類型
if(file_exists($filename)){
$info= getimagesize($filename);
$ext = image_type_to_extension($info['2']);
return stripos($alltypes,$ext);
}else{
return false;
}
}
if(isImage('test.jpg')!==false){
echo '是圖片';
}else{
echo '不是';
}
第二種方法比較強大一些,能判斷多種格式
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2); //只讀2字節
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$fileType = '';
switch($typeCode){
case 7790:
$fileType = 'exe';
break;
case 7784:
$fileType = 'midi';
break;
case 8297:
$fileType = 'rar';
break;
case 255216:
$fileType = 'jpg';
break;
case 7173:
$fileType = 'gif';
break;
case 6677:
$fileType = 'bmp';
break;
case 13780:
$fileType = 'png';
break;
default:
$fileType = 'unknown';
}
return $fileType;
}
第三種方法:
PHP gd類庫函數提供了一個exif_imagetype() 函數, 用來讀取圖像的第1個字節, 還會對圖片的簽名做檢查。 如果格式不對,會返回false。 其實啊, 這個方法和第一種方法有異曲同工之妙。 但是因爲這個是庫函數,效率要比第一種方法高得多。此函數用法很簡單,傳入路徑,然後通過判斷是否等於某個常量, 例如 gif格式的IMAGETYPE_GIF
if(exif_imagetype("image.gif")!=IMAGETYPE_GIF){
echo "The picture is not a gif";
}
第四種方法:php重繪
效率很低的一種方法,但也是一種思路: 把傳輸過來的文件,不論什麼文件都以resource 類型繪到圖片中去, 如果是圖片,能還原出來。如果不是圖片,那繪畫不出來,而且裏面的危險代碼也沒有了。
具體請看:
function isimage($imgpath){
if($imgpath['type']=="image/gif")
$img=imagecreatefromgif($imgpath['tmp_name']);
elseif($imgpath['type']=="image/png" || $imgpath['type']=="image/x-png")
$img=imagecreatefrompng($imgpath['tmp_name']);
else
$img=imagecreatefromjpeg($imgpath['tmp_name']);
if($img==false){
return false;
}else{
return true;
}
}
第五種方法:把二進制的圖片轉換成十六進制的
總結: 我曾經在網上看到過有人說:相信懂得php的人都用過XX函數。 我打開一看,就是一個使用後綴來判斷上傳類型的函數。 同學在做類似功能的時候一定要揭開表現看到本質,否則經過僞裝的圖片在上傳之後,會對服務器造成極大安全隱患。