當前位置: 首頁> 最新文章列表> image_type_to_extension() 使用時不檢查文件格式會出什麼問題?有哪些風險?

image_type_to_extension() 使用時不檢查文件格式會出什麼問題?有哪些風險?

M66 2025-06-23

不檢查文件格式的風險

1.偽造文件類型繞過上傳驗證

攻擊者可以通過將惡意腳本(如PHP 代碼)偽裝成圖片上傳。例如,將一個包含PHP 後門的腳本命名為.jpg.png ,然後上傳。若不使用exif_imagetype()檢測實際文件類型, image_type_to_extension()可能會錯誤地返回合法擴展名,從而誤導後續邏輯,甚至將其保存在可執行目錄中:

 $filename = $_FILES['image']['tmp_name'];
$ext = image_type_to_extension(@exif_imagetype($filename));
// 錯誤用法:沒有檢測exif_imagetype返回值是否為false
$newName = uniqid() . $ext;
move_uploaded_file($filename, "/var/www/html/uploads/" . $newName);

如果上傳的文件並非真實圖片,例如一個偽造的PHP 腳本,但擴展名是.jpg ,攻擊者就可能通過訪問http://m66.net/uploads/xxxx.jpg執行惡意代碼。

2. exif_imagetype()失敗返回false,但仍傳入image_type_to_extension()

exif_imagetype()不能識別文件類型時,它會返回false 。如果此時仍將結果傳入image_type_to_extension() ,會返回.int(0) ,導致生成文件名混亂,甚至邏輯異常。例如:

 $type = exif_imagetype($filename);
$ext = image_type_to_extension($type);
// 如果$type為false,$ext為"."

這樣可能會導致程序使用錯誤的文件擴展名,影響後續操作,甚至造成資源洩露。

3.未開啟fileinfoexif擴展

在某些服務器環境中,如果PHP 沒有啟用fileinfoexif擴展,那麼exif_imagetype()會失效。若仍然依賴其結果並傳入image_type_to_extension() ,程序容易崩潰或處理邏輯錯誤,影響用戶體驗。

4.依賴擴展名的安全策略失效

有些服務部署安全策略是基於擴展名進行限制,比如只允許.jpg.png文件被訪問。如果攻擊者偽造文件名,並繞過後端檢查,服務器可能錯誤地授予訪問權限。

例如,上傳了一個名為.php.jpg的文件,但真實格式是PHP。 Nginx 在某些配置下會將其識別為.php文件而執行,從而產生嚴重後果:

 <?php echo shell_exec($_GET['cmd']); ?>

然後通過訪問:

 http://m66.net/uploads/backdoor.php.jpg?cmd=ls

即可遠程控制服務器。


正確的使用方式

為了避免上述風險,應該採取以下措施:

  1. 使用exif_imagetype()且判斷返回值是否為false

  2. 使用finfo_file()來進一步驗證MIME 類型

  3. 限制上傳目錄不可執行

  4. 不信任用戶提交的擴展名

  5. 使用白名單驗證image_type_to_extension()的返回值

示例代碼:

 $filename = $_FILES['image']['tmp_name'];
$imageType = @exif_imagetype($filename);

if ($imageType === false) {
    die('不支持的圖片格式');
}

$ext = image_type_to_extension($imageType, false);
$allowed = ['jpg', 'jpeg', 'png', 'gif'];

if (!in_array($ext, $allowed)) {
    die('不允許的圖片類型');
}

$newName = uniqid() . '.' . $ext;
move_uploaded_file($filename, '/var/www/uploads/' . $newName);