點評:IE有一個特性,那就是在將一個文件展示給用戶之前會首先檢查文件的類型,這乍看起來並沒什麼問題,但實際上這是相當危險的,因為這會允許IE執行圖片中的代碼,即嵌入在一個圖像中的JavaScript代碼。引入MIME sniffing功能的初衷是用來彌補Web服務器響應一個圖像請求時有可能
IE有一個特性,那就是在將一個文件展示給用戶之前會首先檢查文件的類型,這乍看起來並沒什麼問題,但實際上這是相當危險的,因為這會允許IE執行圖片中的代碼,即嵌入在一個圖像中的JavaScript代碼。引入MIME sniffing功能的初衷是用來彌補Web服務器響應一個圖像請求時有可能返回錯誤的內容類型信息這一缺陷。
但是事不遂人願,心懷不軌的人可以輕易濫用這一特性,如通過精心制作一個圖像文件,並在其中嵌入可以被瀏覽器所展示和執行的HTML和JavaScript代碼。本文將深入考察該問題,並為用戶和網站開發人員介紹如何降低此問題帶來的風險。
一、危險的MIME sniffing功能
對於Web 2.0應用程序來說,允許用戶上載圖像是一項基本的要求。但是,IE用戶面對這些圖片時卻要小心瞭,因為IE的某些功能會為利用圖片進行跨站點腳本攻擊大開方便之門。
雖然許多大型站點都設法保護其訪問者免受可能的JavaScript攻擊,例如實現專門用於防禦活動內容的過濾器等,但是他們卻無法跟活動內容一刀兩斷,因為對於個人簡介、博客和論壇來說,JavaScript、HTML 代碼和Flash小應用程序是不可或缺的活動內容。
此外,大部分交互型站點都允許用戶上載和鏈接他們的圖片,但是攻擊者卻可以利用此功能來顛覆IE為保證兼容性和提供額外的安全性而引入的某些功能。攻擊者隻需在圖像的開頭部分嵌入一些HTML代碼和JavaScript,那麼當IE打開這個做過手腳的圖像時,瀏覽器所做的不是顯示圖像,而是檢測並運行圖像中嵌入的代碼。
之所以出現這種情況,是因為瀏覽器可以用來確定文件類型的方式多種多樣,例如文件擴展名jpg可以指出一個圖像為JPEG格式,此外Web服務器還可以在HTTP報頭中定義Content-Type(在本例中為image/jpg),但是一般說來使用上載的文件的文件名擴展部分來指出文件的類型。
最後,大多數 Web 瀏覽器還會檢查一個文件的開始幾個字節(即通常所說的文件的“簽名”),這幾個字節通常為一些眾所周知的字節序列,例如PNG、PK、JPEG、JFIF等等。
迄今為止,我們介紹瞭瀏覽器可以確定文件內容類型的三種方法,即通過文件本身的擴展名或文件開頭部分的簽名,或通過服務器響應報頭Content-Type來確定文件類型。
不過,後來IE4引入瞭第四種方法,即通常所說的MIME sniffing或者MIME類型檢測方法。所以,現在的IE版本都不自動地假定來自web的文件的內容類型就是服務器在HTTP報頭中的所聲明的內容類型。IE瀏覽器既不信任文件名擴展部分,也不信任簽名,相反,它是通過檢查文件開頭的256字節內容來確定文件的類型。
然而,隻有當用戶直接調用URL下載文件時IE才這樣做。當使用IE打開HTML中的圖像標簽(IMG)所連接的本地存儲的文件或者圖像的時候,則不會進行嗅探。
IE引入MIME sniffing功能的初衷是用來提防服務器給出的錯誤內容類型指示的,但是攻擊者卻利用它來規避IE中的安全防禦功能,即防止瀏覽器自動地執行所下載的文件(如hta文件)的那些功能。
此外,MIME sniffing還使得瀏覽器能夠容忍在Content-Type聲明中的偶然性錯誤,例如,如果服務器聲明某文件類型為text/plain文件,然而實際提供的卻是一個HTML文件,那麼IE將它作為HTML處理。
對於常見的GIF、JPEG和PNG格式,隻要文件擴展名、Content-Type和簽名所指的類型相一致,那麼瀏覽器就會對MIME sniffing所得到的結果置之不理。隻有當文件擴展名、Content-Type和簽名所指的類型有出入時,IE才會以MIME sniffing所確定的結果為準。
二、倒打一耙的MIME sniffing功能
現在,如何保護用戶免受惡意服務器的侵害與如何為不正確地配置服務器的管理員提供有效幫助已經成為Web 2.0所面臨的一大問題。 如果文件的擴展名、Content-Type和簽名相抵觸,那麼瀏覽器會以內容為準。
所以,如果一幅圖片的開頭部分為一些HTML代碼的話,雖然乍一看好像是無害的,但是實際上卻可能相當危險,因為IE會執行圖片中的代碼。這為攻擊者把JavaScript嵌入圖像提高瞭一個機會,所以他們可以利用這種方式執行跨站點腳本攻擊,使用精心制作的圖像來竊取受害者在當前訪問的服務器上的身份驗證cookie,然後以受害者的身份登錄到那個服務器。
三、援兵未至
微軟公司已經認識到這個問題,並計劃IE的新版本中加以修復。IE8不再探測圖像,因此,它會忽略嵌入的HTML。此外,對於特定的下載,還可以通過為私有的Content-Type以及authoritative指定值來關掉MIME sniffing功能,例如content-type=text/html; authoritative=true;。然後,IE會把文件當作服務器指出的類型來處理。
關鍵情況下,可以使用新的“X-Download-Options: noopen”頭部來確保在站點上下文的外部顯示相應的文件,這意味著即使HTML文件也能夠安全的投遞,因為瀏覽器隻是將文件保存起來而已。遺憾的是,IE8要想全面替代其他版本的IE尚需時日,在此之前,Web站點對此還是指望不上的。
四、急救措施
實際上,如今想要抵擋這些精心制作的文件也並非難事。自Windows XP SP2以來,用戶已能禁用IE中的MIME sniffing功能,方法是打開瀏覽器的“工具”菜單中選擇“Internet 選項”,點擊“安全”選項卡,在“請為不同的區域的Web內容指定安全設置(z)”下面選擇“Internet”圖標,在“該區域的安全級別(L)”下面點擊“自定義級別”按鈕,最後啟用“基於內容打開文件,而不是文件擴展名”選項即可。然而,這樣做會重新開放一些以前的古老漏洞!
這是否能夠提供安全性隻能夠靠實踐來證明。我們的重點不應該放在在用戶間推廣這個技巧,而是應該設法讓web服務應用提供安全保障措施來保護訪問者,並確保Web服務提供方的系統不向用戶傳送精心制作的圖像。
管理員可以使用腳本檢查上傳到其服務器中的文件的類型的一致性。舉例來說,如果某圖像的文件名擴展部分為.jpg,並且文件起始字節部分的簽名也指出是相同的類型(在Linux下可以使用file image.jpg命令,而在PHP中可以使用getimagesize加以印證),經過上述驗證後,服務器才能發出該文件。
這樣,即使文件包含HTML 代碼,IE也不會執行這些代碼。然而要註意的是,通過這種方式隻能保護圖像的安全,同時服務器聲明的Content-Type必須完全正確才行。 這個方法對其它格式均不起作用。
然而,要想達到絕對的可靠性,需要檢查文件的前256字節是否HTML 代碼。IE使用常見的< body >、< head >、< html >、< img >、< script >等等標簽來識別HTML代碼。如果在文件的前256字節中沒有發現任何標簽的話,微軟的瀏覽器就無法解釋該文件瞭。
管理員也可以這樣配置服務器,當文件被下載(而非打開)時,服務器總是發出頭部“Content-disposition: attachment; filename="< filename.ext >”。 這樣就能防止瀏覽器在該站點的上下文中打開此文件,而是使用本地鏈接的應用程序來打開此文件,但是這樣做會使用戶感覺很不爽。 遺憾的是,這種頭部重寫技術隻對那些不允許直接訪問文件的用戶有效。
鑒於此,所上傳的文件的存儲位置不應該位於可公開訪問的地方,並且最好為文件隨機命名。
實際上,最有效的方法是使用ImageMagick或者類似的工具來轉換圖像文件的格式。這能從圖像中清除掉所有代碼段,從而徹底擺脫這些代碼為用戶帶來的威脅。
像Facebook和Twitter這樣的大型站點會對用戶上傳的肖像照片進行轉換,但是必須小心行事,因為這有可能打開另一個攻擊方式。例如,如果某人在ImageMagick中發現瞭一個緩沖區溢出問題,那麼攻擊者可能進行一番嘗試,並找到一種利用特制的相片來利用該問題的方法。
五、總結
MIME sniffing功能本是IE的忠誠衛士,誰知他如今突然“倒戈”,助紂為虐來危害IE用戶。對策當然是有,但是這些對策是否靠譜卻是個懸而未解決的問題。目前,通過圖像發動的跨站點腳本攻擊看起來還不太常見,但是世界正在發生急劇的改變:交互型網站正在變成犯罪的首選目標。
好在,我們還可以使用其它的瀏覽器,例如Firefox等,這倒不失為一個補救措施。當然Firefox也進行MIME sniffing,但是它卻不會莫名其妙地將圖像作為HTML進行解釋。