幾個月前,我挖到了一個Twitter的XSS漏洞,同時繞過了站點的內容安全策略(CSP)成功執行了JavaScript代碼。在本篇文章中將主要向大家分享該XSS漏洞挖掘的思路及具體細節,同時在文章中附帶了PoC演示視頻。
漏洞分析
存在漏洞的站點為https://apps.twitter.com,當開發人員創建應用時可以設置服務網站(Website)信息,用于提供對應用程序更加詳細的描述,及應用下載等功能。

經過測試后發現,Twitter的開發人員對該處輸入的內容在服務端的正則校驗可能是這樣:([https?:])\w+
細心的同學可能會發現這個正則表達式的開頭缺少^字符,當我們輸入類似data:CONTENT#https://…這種url是可以通過驗證的,所以此時我們已經獲得了一個HTML注入。由于該站點CSP(內容安全策略)的限制,此處注入HTML代碼并不會解析。
在對HTTP頭檢查后,我注意到script-src和object-src塊中有多個CSP(內容安全策略)配置錯誤,利用這些配置缺陷可能繞過twitter.com的CSP(內容安全策略)。CSP的規則如下所示:
script-src https://connect.facebook.net https://cm.g.doubleclick.net https://ssl.google-analytics.com https://graph.facebook.com https://twitter.com 'unsafe-eval' 'unsafe-inline' https://*.twimg.com https://api.twitter.com https://analytics.twitter.com https://publish.twitter.com https://ton.twitter.com https://syndication.twitter.com https://www.google.com;frame-ancestors 'self';object-src https://twitter.com https://pbs.twimg.com; default-src 'self';...
看到這里,object-src和script-src塊立即引起了我的注意。經過一番分析,我找到一個可信域(cdn.syndication.twimg.com 又名 syndication.twitter.com)主機的JSONP endpoints。
一開始我認為,通過利用object-src塊的內容(https://pbs.twimg.com),這個網站可以將Flash文件(as picture/video extension with few bytes header)上傳到Twitter的CDN服務器,將其作為嵌入式對象(embedded Object)以執行代碼。然而由于對用戶輸入長度的限制,我試圖執行的payload都因為過長而被截斷,所以這種利用方式最后沒有成功。我找到一個可信域下可以利用的點,寫出了一個較短的payload,當注入到twitter.com的時候代碼執行,成功彈窗。
http://syndication.twitter.com/widgets/timelines/246079887021051904?dnt=true&domain=site.com&lang=en&callback=alert
當我們向服務端請求,來自syndication.twitter.com主機的JSONP響應頭有一個Content-Disposition字段強制將返回的內容作為文件下載。但是,Chrome瀏覽器即使將返回的內容作為附件下載但由于配置錯誤的“unsafe-inline”CSP(內容安全策略)塊意味著我們仍然可以執行代碼。
通過設置服務網站(Website)信息如下:
data:text/html,

客戶端代碼將會執行,彈窗。
PoC 演示視頻
后記
在后續的分析過程中我發現ssl.google-analytics.com、www.google.com還有graph.facebook.com主機的JSONP endpoints也可以被利用,我已經將其寫入到向Twitter報告漏洞的郵件中,但官方表示這些問題短期內可能不會被修復,以為這可能影響部分功能的正常使用,同時聯系其他廠商也需要一定的時間。
在這篇文章發布后Twitter上的研究員@Ben Hayak提示,我們也可以在該點展開同源方法執行(SOME)攻擊,像這樣:
https://syndication.twitter.com/widgets/timelines/246079887021051904?callback=
document.body.firstElementChild.Reference.submit
|