CodeIgniter 的文件上傳類通過 application/config/mimes.php 白名單驗證 MIME 類型。默認配置:
application/zip、application/x-zip-compressed,缺少瀏覽器常發送的 application/octet-stream、application/x-zip。<?php
// application/config/mimes.php
return [
// ... 現有配置保持不變 ...
'zip' => [
'application/zip',
'application/x-zip',
'application/x-zip-compressed',
'application/octet-stream', // 關鍵:許多瀏覽器/代理發送此類型
'multipart/x-zip', // 罕見但存在
],
'rar' => [
'application/x-rar-compressed',
'application/octet-stream', // 同理
'application/vnd.rar', // IANA 標準類型
],
// 同理補充其他常見壓縮格式
'7z' => ['application/x-7z-compressed', 'application/octet-stream'],
'gz' => ['application/gzip', 'application/x-gzip', 'application/octet-stream'],
'tar' => ['application/x-tar', 'application/octet-stream'],
];
Content-Type。Upload 類接收 $_FILES['userfile']['type']。_file_mime_type() 讀取 mimes.php 對應擴展名允許的類型數組。The filetype you are attempting to upload is not allowed.僅靠 MIME 白名單仍可被偽造。生產環境建議在控制器中增加魔數檢查:
public function do_upload() {
$config['allowed_types'] = 'zip|rar|7z';
// ...
if (!$this->upload->do_upload('package')) {
$this->session->set_flashdata('error', $this->upload->display_errors());
redirect('upload');
}
$info = $this->upload->data();
// 二次驗證文件頭
$signatures = [
'zip' => [0x50, 0x4B, 0x03, 0x04], // PK..
'rar' => [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00], // Rar!...
'7z' => [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C], // 7z¼...
];
$ext = strtolower(pathinfo($info['file_name'], PATHINFO_EXTENSION));
if (isset($signatures[$ext])) {
$fp = fopen($info['full_path'], 'rb');
$header = fread($fp, 8);
fclose($fp);
$bytes = array_values(unpack('C*', $header));
$match = true;
foreach ($signatures[$ext] as $i => $sig) {
if (!isset($bytes[$i]) || $bytes[$i] !== $sig) { $match = false; break; }
}
if (!$match) {
@unlink($info['full_path']);
$this->session->set_flashdata('error', '文件內容與擴展名不符,疑偽造文件');
redirect('upload');
}
}
// 入庫、業務邏輯...
}
system/libraries/Upload.php → 升級框架覆蓋,違反框架擴展原則。$config['allowed_types'] = '*' → 極度危險,繞過所有類型檢查。application/config/mimes.php,屬於應用配置層,不影響框架核心。CodeIgniter 4 將 MIME 配置移至 app/Config/Mimes.php,結構為關聯數組 'zip' => ['application/zip', ...],修改方式相同。