2011-11-06 152 views
9

在php中檢查MIME類型是非常容易的,但據我所知MIME可以被欺騙。攻擊者可以上傳一個php腳本,例如jpeg mime類型。想到的一件事是檢查上傳文件的文件擴展名,並確保它與MIME類型相匹配。所有這一切都假設上傳目錄是瀏覽器可訪問的。MIME類型欺騙

問題:有沒有其他技術可以防止「壞文件」進入MIME類型欺騙?

+2

是你對MIME類型欺騙的問題,或者你只是想知道如何驗證上傳的文件,以檢查他們是否是圖像文件? – CodeCaster

+0

事實上,你不應該首先依賴MIME類型和文件擴展名(如果MIME->擴展名也是錯誤的;如果我假MIME我可以更容易地僞造一個相應的文件擴展名) –

+0

@CodeCaster:如何確保文件上傳的文件的MIME類型不被欺騙? – abruski

回答

8

簡短的回答:第

較長的答案:

擴展比較,並確保它的MIME類型並沒有真正阻止任何匹配。正如評論中所述,修改文件擴展名更容易。 MIME類型和擴展只能作爲提示,並不存在固有的安全性。

確保傳入文件不會造成傷害,這取決於您的目標是什麼。在你的情況下,我明白你正在期待圖像。因此,您可以首先執行一些完整性檢查:掃描前幾個字節以查看文件是否包含相關的圖像標頭簽名 - 所有相關的圖像格式都具有這些簽名。

「簽名標題」可幫助您決定文件嘗試模擬的圖像格式。在下一步中,您可以檢查其餘內容是否與底層圖像格式兼容。這可以保證你的文件真的是一個特定格式的圖像文件。

但即便如此,該文件可能被細心的方式,當顯示圖像,使用了流行的庫來顯示圖像製作(如libpng的等)會碰上一個緩衝區溢出,攻擊者在發現圖書館。

不幸的是,除了根本不允許來自客戶端的任何輸入外,沒有辦法主動防止這種情況。

+0

圖像只是例子。將處理PDF文件。但我想概括這個問題,所以它也會幫助其他文件類型 – abruski

+1

原理總是相同的。一個聰明的攻擊者會給你你所期望的,但是它會利用最常用的庫來查看這些文件。對於PDF,這意味着他們可能會嵌入Javascript,視頻,圖像......數據格式提供的功能會大大增加選項的數量。如果你(或你的客戶!)永遠不會「執行」(查看也是「執行」)上傳的內容,那麼你纔是安全的。 – emboss

+0

通過使用像GD這樣的庫或ImageMagick這樣的工具將它複製到新圖像中,可以獲得「安全」圖像。對於任何這些庫,沒有任何已知的開放漏洞 - 以前在Windows的GDI中已經有一個,但是從那以後就已經修復了。誠然,從理論上講,沒有安全保障,但有*方法可以安全地處理文件。 –

-4

檢查擴展名。

<?php 

$okFiles = array('jpg', 'png', 'gif'); 

$pathInfo = pathinfo($filename); 

if(in_array($pathInfo['extension'], $okFiles)) { 
    //Upload 
} 
else { 
    //Error 
} 

?> 

你也可以像你說的那樣檢查擴展名是否匹配MIME類型,但是檢查擴展名更容易。

Btw爲什麼你關心MIME類型?

+0

,以確保上傳的文件是它的樣子。想象一下:上傳MIME圖像,但內部帶有ext php和php代碼;上傳目錄是瀏覽器可訪問的,就像我想象的攻擊者可以自由運行一些惡意代碼。 – abruski

+1

@abruski所以你根本不需要檢查MIME類型。只需檢查擴展名。如果它是jpg/png/gif,那沒關係,否則會拋出一個錯誤「Just jpg/png/gif」。不知道這是不是你害怕的東西,但如果擴展名是.jpg和MIME SAIS PHP,當你瀏覽文件時它仍然會被當作圖像處理。 – Sawny

+0

也認爲。只是想確保我走在正確的軌道上。 – abruski

4

在圖像

  • 檢查擴展與那些允許的列表(如「.JPG」,「.JPEG」,「png格式」)的情況下
  • 檢查上傳的文件本身在文件上運行getimagesize,如果它不是圖像,它將返回FALSE。

其他類型的上傳

  • 檢查允許的擴展(如 「.PDF」)
  • 檢查文件的MIME類型對應的擴展

樣品代碼:

function getRealMimeType($filename) { 
    $finfo = new finfo(FILEINFO_MIME, "/usr/share/misc/magic"); 
    if (!$finfo) { 
     echo "Opening fileinfo database failed"; 
     return ""; 
    } 
    return $finfo->file($filename); 
} 

請參閱finfo_file文檔。

+0

它不必是一個圖像,它可以是任何類型的文件。 – abruski

+0

我明白了,讓我擴大答案。 – stivlo

+0

多數民衆贊成如果getimagesize返回false,如果它不是一個圖像:-)非常有用的檢查ID猜測,但如果擴展是欺騙和MIME類型呢? –