在某個客戶的電腦上上傳excel時,excel mime-type類型爲application/octet-stream

問題

在某個客戶的電腦上上傳excel時,mime-type類型爲application/octet-stream 無法通過後臺驗證

交互流程

用戶使用wps創建文件保存格式爲mime-type->用戶上傳excel->瀏覽器獲取文件mime-type 並在請求體中傳遞Content-Type: 瀏覽器獲取的mime-type->傳遞到服務器並驗證文件的mime-type->不通過,返回錯誤給前端
clipboard.png

猜測原因

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:
clipboard.png
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
clipboard.png
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的函數 finfomime_content_type

問題及拓展

1.文件的類型的二進制約定方式(查找RFC)
2.瀏覽器怎麼獲取文件的mimet-type

參考

阮一峯-mime-type
mime-type
文件上傳
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章