最近更新: 2010-10-21

Padding Oracle Attack 與 Web 軟體開發框架

今天在 InfoQ 看到一篇關於破解金鑰加密技術的文章,Padding Oracle 漏洞影响JSF,RoR及ASP.Net。這篇文章的主要檢驗對象,是那些將用戶、表單等資料,經由金鑰加密方式,傳送給 Web 客戶端的 Web 軟體開發框架。破解理論及範例,都可以在作者 Juliano Rizzo & Thai Duong 的網站上找到,請參考 Rizzo 的網站: netifera.com

利用 Padding Oracle 漏洞 (PO),攻擊者不需要私鑰,就能在可預期的嘗試次數中,解出加密資料的原始內容。The attack works within a complexity of O(NbW) in order to decrypt the message where W is the number of possible words (typically W = 256)(Serge Vaudenay, 2002). 我不懂密碼學的理論,但看了作者示範的破解影像《Cracking CAPTCHA with Padding Oracle attack》後,我猜想在某些狀態下,破解這種加密方式的通行碼之所需時間,短於破解雜湊法處理的通行碼。

攻擊者一般使用窮舉法破解 MD5, SHA 這類雜湊法處理的資料(因為MD5,SHA是對資料進行雜湊運算,其結果不能還原,故嚴格來說並不是「加密」方法)。就結果而言,不是全對就是全錯。但是對於應用了 RFC 2040 Cipher Block Chaining 演算法加密的資料,攻擊者運用 PO 漏洞,卻可以逐字地還原資料。這也意味著原始資料內容就算是隨機組成的字元、或是二進位資料文件,它都可以有效地還原全部或一部份內容。

接著我們看看 Web 軟體開發框架在這方面又犯了什麼毛病?

Juliano Rizzo & Thai Duong 的報告中,主要示範的攻擊對象是 JSF,不過 ASP.Net 也有相同的問題。我在以前任職的公司開發過 ASP.Net 的案子,所以對於 ASP.Net 中的 ViewStatus 仍有著深刻的記憶。ASP.Net 大量地使用 ViewStatus 實現狀態持續機制。各種控制元件的資料(包含變數以及使用者填寫的表單內容),加密之後,透過 ViewStatus 在客戶端與伺服端之間來回傳遞。這是最受 PO 漏洞喜愛的活動環境。根據 InfoQ 的報導,微軟在收到作者的通知後,緊急在十天後發佈了一項計劃外的安全更新,顯示 ASP.Net 受到地威脅有多麼嚴重。

有趣地是,PHP 在這波威脅中,處於低風險區。在我的印象中,PHP 似乎還沒有開發框架透過 ViewStatus 這種途徑支援狀態持續機制,因此 PHP 程序員得要自己處理這事。PHP 程序員在保存使用者狀態時,通常有兩種做法。第一,以明文形式,在客戶端與伺服端之間傳送使用者的狀態資料。第二,用 PHP Session 。

第一種的明文方式,就算沒有這篇 PO 漏洞報告,我們也毫無疑義地知道這是一種很愚蠢的方式。不需要討論。

第二種的 PHP Session 方式,則是將使用者狀態資料儲存在伺服端;傳送給客戶端的只是一個與使用者資料內容無關的鍵值(SessionID) 。PHP 使用這個鍵值,存取在伺服端的使用者狀態資料。在它的處理過程中,使用者的狀態資料並不會被傳送到客戶端,故而倖免於 PO 漏洞之威脅。

Juliano Rizzo & Thai Duong 的報告中提到了幾點防治措施。

  • 關閉你的開發框架預設的錯誤輸出訊息。這其實是一項廣泛而通用的安全守則。開發人員也許很討厭看到 Servlet, ASP.Net 或 PHP 網站丟出的錯誤訊息頁,但是攻擊者很高興看到這些內容。因為那些內容不只提供開發人員除錯的資訊,也為攻擊者提供了入侵方式的提示訊息。PHP 程序員謹記,開發時期將 error_reporting 設為 E_ALL;部署到客戶系統時,必須將 error_reporting 設為 0 。
  • 如非必要,不要把使用者狀態資料傳送到客戶端。在我的經驗中,還真的很少遇到必須在客戶端保存狀態資料的案例。就算有必要, PHP Session 的解決方案也是更為理想的方案;我大部份時候都用 PHP 開發網站,採用這種方案是天經地義的事。
  • 對於傳送到客戶端的狀態相關資訊,確認其完整性。逾時失效就是一種常見的保護。
  • Ruby on Rails: 報告中指出,檢查你用到 ActiveSupport::MessageEncryptor 的程式碼。Fortunately, ActiveSupport::MessageEncryptor is not widely used.(Juliano Rizzo & Thai Duong, 2010)
樂多舊網址: http://blog.roodo.com/rocksaying/archives/14245311.html

樂多舊回應
hoamon@hoamon.info(hoamon) (#comment-21339521)
Thu, 21 Oct 2010 21:42:54 +0800
我還真想不出還有什麼是比用 session 來紀錄使用者資料的更好方法。只要用瀏覽器上一組編號,就可在伺服器端以檔案、資料庫或是記憶體快取來紀錄使用者資料,我一路從 perl, php, python 走來,還真沒想過要把使用者資料記在瀏覽器 cookies 中。

果然我不適合 .Net 。
hoamon@hoamon.info(hoamon) (#comment-21361745)
Sat, 30 Oct 2010 23:17:03 +0800
剛剛在 http://blog.gslin.org/archives/2010/10/29/2326/%E6%9C%80%E8%BF%91%E5%BE%88%E7%B4%85%E7%9A%84-firesheep 看到利用 firesheep 去抓取其他人的瀏覽器 cookie 。所以,其實用 session 也沒法保證真的安全了。
未留名 (#comment-21368417)
Tue, 02 Nov 2010 18:03:46 +0800
firesheep 也算是一種木馬了吧。首先要騙取終端使用者的信任,才能在終端使用者的電腦上安裝。要防也不是防不了的。

不過有些人的戒心就是薄如紙,就是有喜好胡亂地安裝一些「外掛」程式的使用者。我只能說他們是自取其禍。
未留名 (#comment-22049121)
Fri, 14 Oct 2011 11:39:22 +0800
ASP.NET 也有 Session 吧,這是每一個 server side 語言必備的不是嗎?ASP.NET 提供 ViewState 來方便程式設計師有另外一種儲存方式,卻要被人家嫌這說不過去吧。我不知道樓上的發言者到底真不真正的有操作過 .NET 或是瞭解,基本上一個熟練的 ASP.NET 程式設計師是不會把 ViewState 拿來放正式需要驗證或儲存某種正式資料的,頂多拿來維繫這一頁的 UI 狀態,以防 reload 後消失。真正在運作程式時,.NET 設計師甚至可以把 ViewState 全關掉,這一點你沒見過吧!?建議不要以管窺天,然後在網路發酸文比較好。
未留名 (#comment-22049149)
Fri, 14 Oct 2011 12:05:33 +0800
to Slash:

這篇回應是針對正文嗎? 我看不出正文哪裡在酸 ASP.Net 的 ViewState.

再說了,我也確實用過 ASP.Net (正文中有說),也很清楚按照 ASP.Net 的預設儲存機制,頁面控制項的狀態(ViewState)真的是用加密方式保存在表單中。所以微軟很快地發佈了安全更新。

程序員可以自已決定控制項的狀態要不要納入ViewState維護,不過全關掉的情形倒很少見。
我記得根據 MSDN 的說法,session 是 ViewState 其中一種可選的儲存機制。一般來說,程序員不會為了安全性而關掉全部的 ViewState,而是設定用 session 來儲存 ViewState。
因為全關掉的話,那 ASP.Net 不就跟 PHP 一樣,要程序員自己維護持續狀態了嗎?這樣 ASP.Net 的主要優勢就沒了。