在這篇文章中,我們詳細講述一個在Facebook 上發現的服務器安全漏洞,這個漏洞可能會影響數百萬CORS(跨域資源共享)中Origin頭允許“NULL”值的網站,該漏洞會威脅用戶的隱私,惡意實體可以不受限的訪問網站。被稱為“Originull”的攻擊方法,允許黑客訪問和瀏覽到所有經過Facebook Messenger發送的私人聊天記錄、照片、和其他附加信息。這個安全問題是由Ysrael Gurt研究團隊發現的,目前已經通知了Facebook。
“非技術性”的解釋
這個漏洞是一個跨域權限繞過攻擊漏洞,允許黑客利用外部網站訪問和讀取到用戶的Facebook 私人消息。通常,瀏覽器會保護Messenger用戶,只會讓Facebook 頁面訪問到這些信息,但是,Facebook 為了使它的子網站能訪問到Messenger的信息,它打開了一座能讓子網站訪問到信息的“橋”。如果惡意程序能成功利用Facebook 管理的子網站的身份,就有可能訪問到Messenger的私人聊天記錄。
例如,如果一個用戶打開了一個黑客的惡意鏈接,這個黑客就有可能看到所有Messenger用戶來往的聊天記錄、照片、和其他信息。
Image 1: The chat appears on the BugSec website. The user ID is shown to the lef
“技術性”的解釋
這是對以上問題更深層次的研究。Facebook Messenger聊天記錄的管理是在一個子域名下,地址是:{number}-edge-chat.facebook.com,而聊天本身是運行在www.facebook.com域名上。
客戶端javaScript和服務器的通信通過XML HTTP Request(XHR)。
javaScript為了訪問到來自5-edge-chat.facebook.com的數據,Facebook 必須在調用者的HTTP頭增加“Access-Control-Allow-Origin”值,且“Access-Control-Allow-Credentials” 的值為“true”,只有這樣,數據才能被訪問(需要cookies)。
Image 2:The original request
到目前為止,這看起來好像是一個正常的跨域資源共享進程。同時為了阻止其他非法的網站訪問這些數據,Facebook對訪問的請求頭會做檢查。如果請求來自一個沒有認證的源,服務器會返回帶有“x-fb-chat-failure-reason”頭的請求錯誤(HTTP 400)信息。
Image 3: Request from a different origin
但是!但是!但是!:Facebook也允許正常GET請求訪問聊天域名。但正常GET請求不帶有XHR的控制標識頭。XHR控制標識頭比較特殊,只有使用XHR請求的瀏覽器對會發送。
當服務器收到GET請求時,它沒有包括CORS的“origin”頭。在很多開發語言中,不存在的頭標識會被解釋成“NULL”值,如果Facebook會接受“origin”頭為“NULL”值的話,它就不會阻止來自這個源的請求。
最有可能的是,過濾機制和響應機制是分開的,響應者假設“origin”頭的值是允許的,因為如果沒有允許,過濾器肯定已經阻止了這個請求。這種開發設計允許Facebook添加一個新的授權訪問源,只需要在一個位置修改一下代碼。
總之,“origin”值為”NULL”的GET請求繞過了過濾檢查。響應者接受了請求頭中的”NULL”值,并且在響應頭中的“Access-Control-Allow-Origin”值中呈現了出來。
Image 4: Request without origin.
到此,已經清楚了,我們發了一個origin為“NULL”的請求,返回頭中帶有“Access-Control-Allow-Origin”標識,且為”NULL”值。
首先,我們用“burp”來檢驗這個結果,當我們發送了“NULL”的請求時,在Facebook的返回信息得到了驗證。
Image 5: Request with “null” origin
在這次測試中,我們也發現了在發送origin為“NULL”的請求時,“data URI scheme”可以被使用,(data URI scheme 允許我們使用內聯的方式在網頁中包含數據,目的是將一些小的數據,直接嵌入到網頁中,從而不用再從外部文件載入)。當使用這功能時,瀏覽器為安全目的,會將origin值默認設置為“NULL”。
Image 6: The example code.
Image 7: The final HTML
Image 8: The HTML in Firefox.
Image 9: The HTML in Chrome
因此,基于實際測試,我們知道了Facebook的處理方法,我們對Messenger聊天用戶,可以進行有效攻擊了。
Facebook聊天API
Facebood會向服務器發送連續的XHR請求,用來獲取新的消息。當收到一個消息或超時,服務器會發出響應。這種方式意味著總會總有一個XHR請求,在等待服務器的返回。當一個服務器返回一個請求時,JavaScripy代碼給服務器又會發送一個新的請求。
Image 10: Server response at timeout.
Image 11: Server response for a new message.
為了確保消息以正確的順序到達,每個請求都有一個序列號(返回的“序列”和請求是對應的)。也就是說每一個請求所用到的參數可以從返回值中得到。
基于以上研究,我們編寫了下面的代碼,這個代碼會和Facebook API進行通信,并竊取到用戶的消息、顯示在頁面上,并發送到BugSec服務器上。如下:
并將這個代碼轉換成Base64字符串,用data URI scheme的方式插入到元素標簽中。
當受害人點擊了惡意網頁(為什么需要用戶點擊,因為需要COOKIES),代碼開始監聽他的Facebook Messenger聊天,并將聊天記錄發送到bugsec服務器。
通過Facebook的漏洞獎勵計劃,這個漏洞已經報告給了Facebook,他們反應很快,幾天前已經對這個漏洞進行了修補。
來源:安全客