歡迎光臨
每天分享高質量文章

延長 XSS 生命期

XSS 的本質仍是一段腳本。和其他文件元素一樣,頁面關了一切都銷毀。除非能將腳本蔓延到頁面以外的地方,那樣才能獲得更長的生命力。

慶幸的是,從 DOM 誕生的那一天起,就已為我們準備了這個特殊的功能,讓腳本擁有突破當前頁面的能力。

下麵開始我們的續命黑魔法。

反向註入

一個不合理的標準,往往會埋下各種隱患。

按理來說,只有通過腳本彈出的頁面,才能擁有 opener 屬性。然而事實上,通過超鏈接點開的頁面居然也有。這為 XSS 打開了一扇大門 —— XSS 不僅可以操控當前頁面,甚至還能傳染給同源的父頁面。

XSS 一旦感染到父頁面里,戰鬥力就大幅提升了。

可以想象,只要看了一個帶有 XSS 的帖子,即使立即關了,那麼帖子串列頁也會遭到感染。

更有趣的是,opener 這個屬性不受同源策略限制。即使父頁面不同源,但父頁面的 opener 仍然可以訪問。

我們可以順著 opener.opener.opener… 一直往上試探,只要是和當前頁面同源的,仍然能夠進行操控 —— 儘管中間隔著其他不同源的頁面。

網站的主頁面顯然比詳細頁更受用戶的信任,停留的時間也會更長,因此攻擊力可成倍的增加。

正向註入

如果說反向註入是苟且偷生的話,那麼正向註入就是當家做主翻身的機會了。

儘管我們能夠控制父頁面,但從父頁面點開的網頁仍然不受操控。如果具有控制子頁面的能力,那就更完美了。

不幸的是,我們無法控制超鏈接打開的新頁面。唯一能夠操控的新頁面,那就是 window.open 的彈框頁。幸運的是,在絕大多數瀏覽器上,它們看起來的效果是一樣的。

因此,我們可以在用戶的點擊瞬間,屏蔽掉預設的超鏈接行為,用彈框頁取而代之,即可把 XSS 註入到 window.open 傳回的新頁面里了。

類似的,通過子頁面遞迴打開的新頁面,同樣也無法逃脫。於是子子孫孫盡在我們的掌控之中。

反向註入,讓我們占據已有的地盤;正向註入,把我們的勢力擴大蔓延出去。兩者結合,即可占據半壁江山了。

值得註意的是,正向註入中有個細節問題。並非所有的超鏈接都是彈出型的(_blank),也有不少是在當前頁面跳轉的。若是想劫持的狠點,可以忽略這個問題;如果不想被細心的用戶發現,那麼可以判斷下當前超鏈接以及的 target 屬性,決定是否劫持。

頁面監督

上面提到,如果是在當前頁面里跳轉,那麼還能繼續感染嗎?或者說,某個頁面掃清之後,是否就丟失了?

答案是肯定的。如果我們不採取一些措施,任憑占據的地盤不斷丟失,那麼我們的勢力範圍就會越來越小,直到消亡。

相比進攻,防守則更為困難。我們不知何時會失去,因此必須定時去檢查。

一旦發現對方已擺脫我們的控制,那麼必須立即重新註入,以恢復我們的勢力。

對於新頁面的 XSS 來說,當然是註入的越早越好。越前面擁有越高的優先級,甚至可以攔截頁面的正常業務功能。

為了能儘快獲知頁面掃清、跳轉等行為,我們還可跟蹤 unload 事件,在頁面即將丟失的瞬間,將訊息通知出去,讓對方儘快來拯救自己。

當然,並非任何情況都能收回的。如果跳轉到了不同源的頁面,那顯然是無能為力了 —— 不過,就此而放棄它嗎?回答是:決不妥協!

儘管頁面已經和我們分道揚鑣了,但所在的窗體仍然被我們掌控。我們可以跳轉、關閉它,甚至還有可能出現奇跡:只要頁面跳轉回我們的站點,又可被我們所收復!

互相聯結

不難發現,只要還有一個頁面存在,就有可能收回曾經被占領的地盤。因此,我們要將可控的頁面都聯結起來,讓每個頁面都知曉並監督所有成員。

當有新成員加入時,通知給大家,記錄在各自的頁面里。

這樣即使其中一個頁面意外關閉了,也不會丟失重要的信息 —— 信息已被分佈儲存在各個頁面里了。

因此,頁面開的越多,相互聯結就越牢固。

如果只剩最後一個頁面,那麼一旦掃清之後就沒人來拯救了,於是就會消亡。

所以,把超鏈接都變成新頁面中打開,還是有很大的優勢的。

降域嘗試

一些網站為了方便通信,將 document.domain 降到根域。例如支付寶網站的絕大部分頁面,都是 alipay.com。這樣原本不同源的子站,這時也能夠相互操控了。

因此,遇到不同源的頁面,可以嘗試降低自身的域,再次發起操作,或許就能成功註入了。

表單劫持

之前說到正向註入,是通過劫持超鏈接點擊實現的。事實上,除了超鏈接外,還有個進入新頁面的方式,那就是表單提交。

相比超鏈接,表單顯得棘手一些。我們不僅得打開一個新頁面,還要把表單里的資料也提交上去。如果把整個表單的元素克隆到新頁面提交,一些資料又會丟失。

不過,仔細研究一下表單元素,會發現有一個非常簡單的方法:原來 window.open 第二個引數可以賦予新視窗一個 name,然後將 name 賦予表單的 target 屬性,即可在我們創建的新視窗里提交。這樣就可以把 XSS 註入進去了。

框架註入

不同頁面之間可以正反註入。同個頁面中,可能存在多個框架頁,因此還可以嘗試框架頁之間的上下註入。

也許,XSS 位於頁面中某個小框架。如果只局限於自身頁面,那麼是毫無發展空間的。因此得跳出圈子,向更廣闊的 parent 頁面註入。

類似的,如果主頁面僅僅是個外殼,實際內容運行在某個框架里,那麼得註入到子框架中,才能獲取更有意義的信息。

同樣,我們還可以將上下註入結合,即可讓 XSS 從某個框架頁里破殼而出,感染到所有的框架頁里。

後記

儘管這些特征從 DOM 誕生起就已存在了,不過要寫出一個完善的腳本並不容易。直到如今的 IE 11,不同窗體間的操作,仍有各種奇怪問題,更不用說那些非主流 IE 了。

不過好在除 IE 外的其他主流瀏覽器,都能很好的運行。下麵分享一個 Demo,其中實現了上述部分功能:

http://www.etherdream.com/FunnyScript/XSSGhost/

當我們順著超鏈接往前點,一旦進入有 XSS 的頁面,先前的父頁面都遭到感染。更嚴重的是,被感染的頁面打開的子頁面,也都無一幸免。即使掃清,也會被其他頁面監控到,從而立即恢復。

正如幽靈鬼魂一般揮之不去。

來自:EtherDream的博客

鏈接:http://www.cnblogs.com/index-html/p/xss_long_live.html

赞(0)

分享創造快樂