有一段圖片上傳驗證,高分幫小弟我找漏洞
來源:互聯網
上載者:User
有一段圖片上傳驗證,高分幫我找漏洞
我的一個小網站http://hitaow.sinaapp.com中有一段代碼,下面是一段PHP圖片上傳驗證的代碼,有個駭客說有漏洞,幫我找下漏洞。找到給分。
if (is_uploaded_file($_FILES['upfile']['tmp_name'])){
$upfile=$_FILES["upfile"];
$name = $upfile["name"];
$type = $upfile["type"];
$size = $upfile["size"];
$tmp_name = $upfile["tmp_name"];
$error = $upfile["error"];
switch ($type) {
case 'image/jpg' : $ok=1;
break;
case 'image/jpeg' : $ok=1;
break;
case 'image/pjpeg' : $ok=1;
break;
case 'image/gif' : $ok=1;
break;
case 'image/png' : $ok=1;
break;
case 'image/x-png' : $ok=1;
break;
}
}
?>
if($ok && $error=='0'){
move_uploaded_file($tmp_name,'../img/index/'.$name);
echo "圖片上傳成功
";
}
if(is_uploaded_file($_FILES['upfile']['tmp_name']) && $ok!=1){
echo "圖片上傳失敗,上傳的圖片應該為:jpg jpeg gif png格式!
";
}
這段代碼我也覺得有漏洞。怎麼才能繞過這段驗證呢。幫我找一下。
------解決方案--------------------
妖氧一段斤你看看
作者:老王
最爛的方法就是通過$_FILES[...]['type']來檢測上傳檔案的類型,因為只需簡單修改副檔名就可以偽造它。
另一個相對安全點的方法是通過檔案頭兩個位元組的內容來判斷上傳檔案的類型,例子代碼如下:
01 $handle = fopen($_FILES[...]['tmp_name'], 'rb');
02 $content = fread($handle, 2);
03 fclose($handle);
04
05 $info = unpack('c2chars', $content);
06
07 if (empty($info['chars1']) || empty($info['chars2'])) {
08 exit('Error!');
09 }
10
11 if ($info['chars1'] < 0) {
12 $info['chars1'] += 256;
13 }
14 if ($info['chars2'] < 0) {
15 $info['chars2'] += 256;
16 }
17
18 $code = $info['chars1'] . $info['chars2'];
PHP中的pack&unpack函數很炫,有興趣的可以看:Handling binary data in PHP with pack() and unpack()
註:網上搜尋的大多數相關的程式沒有做256的相關操作,這是我通過實驗資料自己意淫的TDD結果,不肯定是否一定正確,讀者自己斟酌。
通過switch判斷$code變數,就可以對應到檔案類型,常見的圖片類型結果大致如下:
GIF:7173
JPG:255216
PNG:13780
當然也可以判斷其他的檔案類型,自己做做實驗就知道數值大小了。但此方法也不是一定安全的,因為前兩個位元組的內容也是可以偽造的,所以最好還要限制一下檔案的副檔名,以防意外的解析,比如說,你建立一個名為foobar.php的檔案,內容如下:
GIF89
當你使用前兩個位元組去檢測檔案類型的時候,就會得出GIF:7173的結果,即便使用shell下的file命令去檢測,一樣會誤認為是GIF圖片:
# file foobar.php
foobar.php: GIF image data 16188 x 26736
由於副檔名是.php,那麼此檔案就被php引擎解析了,如此一來就給了駭客一個web shell,安全也就無從談起了。所以說限制副檔名非常重要,切記!至於已經如何發現這類偽裝,最簡單的方法是在用shell命令過濾一遍:
# strings foobar.php | grep -i "
如果想徹底屏蔽此類危險,可以考慮使用gd,imagemagick,graphicsmagick等工具把使用者上傳的圖片進行必要的編輯後再轉存,這樣就能抹去可能的內嵌程式碼。如果想更安全點,還應該把圖片伺服器獨立出來,不裝php,只解析靜態檔案。
補充:如果僅僅是判斷圖片的話,還有一個更簡單方法,那就是getimagesize,這個方法雖然從名字上看是用來取得圖片大小的,但結果裡包含了圖片類型,另外,雖然這個方法在文檔裡被歸納在GD部分,但是即便沒有安裝GD,也是可用的,不過和前面一樣,也要注意安全問題。
------解決方案--------------------
你只判斷檔案的尾碼 比如我上傳 一個圖片 1.jpg 我把尾碼改為 1.php;1.jpg 你的程式會允許存取嗎? 合格特色的尾碼在iis6.0是可以當作php來解析了 如果你檔案儲存檔案時沒自動改名的話 那麼漏洞就產生了
------解決方案--------------------
可以把可以執行的PHP檔案偽裝成圖片檔案,肯定可以繞過。