最近David Leo在Full Disclosure上爆出了一個ie的uxss漏洞,可以繞過ie的同源策略。本文簡要分析一下這個漏洞的原理。
攻擊過程
<iframe src="redirect.php"></iframe>
<iframe src="https://www.google.com/images/srpr/logo11w.png"></iframe>
<script>
top[0].eval('_=top[1];alert();_.location="javascript:alert(document.domain)"');
</script>
poc中第一個 iframe 利用一個302跳轉,跳轉到目標域,第二個iframe也加載了目標域的一個資源,和兩個資源可以是不同的資源,當然跟Content-Type也沒有關系。
上述 poc 在瀏覽器中的渲染過程大概如下:
1、瀏覽器渲染第一個 iframe,并加載 redirect.php 的資源;
2、瀏覽器渲染第二個 iframe,并加載對應的資源;
3、瀏覽器在第一個 iframe 上執行 eval 中的 js 腳本,分為一下幾個步驟:
a.將第一個 iframe 賦值給一個變量
b.彈出一個alert 框
c.用戶關閉 alert框
d.通過給 location 賦值的方式,在目標域上執行 payload
4、payload 在第一個 iframe 所在的域中執行,也就是目標域。
漏洞真相
貌似漏洞的關鍵在那個 alert 彈窗,由于 js 是單線程運行的,所有的彈窗(alert, prompt, and confirm)還有異步函數都會阻斷瀏覽器進程,但是,這塊的邏輯根據瀏覽器的不同,實現也有所不同。來看看上面的 POC 在不同瀏覽器上的渲染時間圖:
FireFox
當alert框彈出的時候,firefox 會繼續處理網絡請求,當第一個 iframe 跳轉,并且加載了目標域的資源之后,alert 彈窗將會被自動關閉,js 腳本停止執行,所以,后續payload 代碼不會執行。
Chrome
當alert 彈窗彈出的時候,所有網絡請求都終止了,所有后續 payload 中的 js 還是在原有的域上執行的。
IE
當 alert 彈窗彈出的時候,IE 會繼續處理網絡請求,當第一個 iframe 跳轉之后,目標域的資源加載完成之后,用戶關閉彈窗,payload 后續的代碼是在目標域上執行的。
本質原因
當第一個 iframe 跳轉之前,payload 中的 js 都是在原有的域上執行的,這不會繞過 SOP,然而,當第一個 iframe 跳轉之后,IE 會轉換相關的域。所以,之前 payload 中的 js 腳本的域切換到目標域了,而不是原本的域,所以,就可以在目標域上執行任意代碼。注意,這里第二個 iframe 也是必須的。
利用成本&&其他
根據現有的 payload,貌似整個利用過程需要用戶參與,事實上并非如此,看如下 payload:
<iframe src="redirect.php"></iframe>
<iframe src="https://www.google.com/images/srpr/logo11w.png"></iframe>
<script>
top[0].eval('_=top[1];with(new XMLHttpRequest)open("get","sleep.php",false),send();_.location="javascript:alert(document.domain)"');
</script>
alert 彈窗的目的是阻塞瀏覽器進程,上面 payload 用一個異步請求來達到同樣的效果。
影響范圍
目前 win7-win8.1上面的 ie10-ie11都受影響。
建議普通用戶先切換到其他瀏覽器吧。