問題
在某個客戶的電腦上上傳excel時,mime-type類型爲application/octet-stream 無法通過後臺驗證
交互流程
用戶使用wps創建文件保存格式爲mime-type->用戶上傳excel->瀏覽器獲取文件mime-type 並在請求體中傳遞Content-Type: 瀏覽器獲取的mime-type->傳遞到服務器並驗證文件的mime-type->不通過,返回錯誤給前端
猜測原因
1.可能wps的某個版本將excel的mime-type類型保存爲application/octet-stream 或者其他瀏覽器無法識別的類型也默認爲application/octet-stream,而在我們的電腦上,wps版本較新,保存的文件mime-type爲 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
2.我們在後臺驗證mime-type的合法性時,一般都會這樣驗證:
'application/vnd.ms-excel',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
3.所有在客戶的電腦上不能通過,在我們的電腦上可以
3.而thinkphp5在獲取上傳文件時,檢測上傳文件的type 是根據瀏覽器傳遞過來的,這樣就會造成一些問題,也是更嚴重的 文件上傳漏洞
參考鏈接:MIME
上傳文件mime類型僞造測試
工具: fiddler
代碼:
<?php
$allowExcelMimeType = [
'application/vnd.ms-excel',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
];
$allowExcelExt = [
'xls', 'xlsx',
];
$fileInfo = $_FILES['fieldNameHere'];
$pos = mb_strripos($fileInfo['name'], '.', 0, 'utf8');
$ext = mb_substr($fileInfo['name'], $pos + 1);
$destination = md5(time()) . '.' . $ext;
move_uploaded_file($fileInfo['tmp_name'], $destination);
var_dump($fileInfo);
$mimeType = mime_content_type($destination);
echo '文件類型:'.$mimeType.PHP_EOL;
if (!in_array($ext, $allowExcelExt, true) || !in_array($fileInfo['type'], $allowExcelMimeType, true)) {
echo '非法的文件類型:'.$mimeType.PHP_EOL;
exit();
}
echo '上傳成功';
excel正常上傳返回數據:
D:\3_tools\wamp\www\test-some\16.upload.php:22:
array (size=5)
'name' => string 'test.xlsx' (length=9)
'type' => string 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' (length=65)
'tmp_name' => string 'D:\3_tools\wamp\tmp\php6F55.tmp' (length=31)
'error' => int 0
'size' => int 17300
文件類型:application/octet-stream 上傳成功
excel 文件僞造mime-type:
D:\3_tools\wamp\www\test-some\16.upload.php:22:
array (size=5)
'name' => string 'test.xlsx' (length=9)
'type' => string 'application/so-cool' (length=19)
'tmp_name' => string 'D:\3_tools\wamp\tmp\php2008.tmp' (length=31)
'error' => int 0
'size' => int 17300
文件類型:application/octet-stream 非法的文件類型:application/octet-stream
僞造php文件mime-type,創建一個php文件,將後綴改爲xlsx
D:\3_tools\wamp\www\test-some\16.upload.php:22:
array (size=5)
'name' => string 'test.php.xlsx' (length=13)
'type' => string 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' (length=65)
'tmp_name' => string 'D:\3_tools\wamp\tmp\php133E.tmp' (length=31)
'error' => int 0
'size' => int 17
文件類型:text/x-php 上傳成功
總結
利用這個漏洞,我們可以跳過一些檢測不嚴格的文件上傳,上傳一些不好的代碼帶服務器並執行
解決方案
在php中有獲取文件真正的mime-type的函數 finfo 和 mime_content_type
問題及拓展
1.文件的類型的二進制約定方式(查找RFC)
2.瀏覽器怎麼獲取文件的mimet-type
參考
阮一峯-mime-type
mime-type
文件上傳