跳转至

(CVE-2020-4054)Sanitize 跨站脚本漏洞

一、漏洞简介

于2020/06/16,Ruby Sanitize项目官方发布了编号为``CVE-2020-4054的[漏洞公告](https://github.com/rgrove/sanitize/security/advisories/GHSA-p4x4-rw2p-8j8m),当Sanitize模块的过滤规则被配置成RELAXED时,利用该漏洞可以绕过该模块的安全过滤功能。具体配置信息可以查看lib/sanitize/config/relaxed.rb`文件。

二、漏洞影响

Sanitize 3.0.0及之后版本(5.2.1版本已修复)

三、复现过程

漏洞分析

HTML语法过滤基础思路

这部分将讲述恶意HTML文本的检测思路与过滤手法,有相关经验的大佬可以直接跳过。

Sanitize是一个用于检测HTML恶意语法并过滤的Ruby模块,其基于白名单的工作方式,提取到输入内容中的HTML标签后,分析并删除不在白名单内的标签,随后生成相对安全的HTML内容,用户可自定自己的白名单规则(例如,只允许<b><i>标签),不过该模块有一些默认的规则内容,接下来我会分析RELAXED过滤规则场景下的默认可信标签,列表如下:

&lt;a&gt; &lt;abbr&gt; &lt;address &lt;article&gt; &lt;aside&gt; &lt;bdi&gt; &lt;bdo&gt; &lt;blockquote&gt; &lt;body&gt; &lt;br&gt; &lt;caption&gt; &lt;cite&gt;
&lt;code&gt; &lt;col&gt; &lt;colgroup&gt; &lt;data&gt; &lt;dd&gt; &lt;del&gt; &lt;dfn&gt; &lt;div&gt; &lt;dl&gt; &lt;dt&gt; &lt;figcaption&gt; &lt;figure&gt; &lt;footer&gt;
&lt;h1&gt; &lt;h2&gt; &lt;h3&gt; &lt;h4&gt; &lt;h5&gt; &lt;h6&gt; &lt;head&gt; &lt;header&gt; &lt;hgroup&gt; &lt;hr&gt; &lt;html&gt; &lt;img&gt; &lt;ins&gt; &lt;kbd&gt; &lt;li&gt; &lt;main&gt; &lt;mark&gt; &lt;nav&gt; &lt;ol&gt; &lt;p&gt; &lt;pre &lt;q&gt; &lt;rp&gt; &lt;rt&gt; &lt;ruby&gt; &lt;s&gt; &lt;samp&gt; &lt;section&gt; &lt;small&gt; &lt;span&gt; &lt;strike&gt; &lt;style&gt; &lt;sub&gt; &lt;summary&gt; &lt;sup&gt; &lt;table&gt; &lt;tbody&gt; &lt;td&gt; &lt;tfoot&gt; &lt;th&gt; &lt;thead&gt; &lt;time&gt; &lt;title&gt; &lt;tr&gt; &lt;ul&gt; &lt;var&gt; &lt;wbr&gt;

HTML恶意检测的工作大致分为三步:

  • 将HTML解析为DOM树

  • 从DOM树中删除不可行的标签和属性

  • 将新的DOM树序列化为HTML标签

{=html}<!-- --> - 举个例子,当输入内容如下时:

    ABC&lt;script&gt;alert(1)&lt;/script&gt;&lt;img src=1 onerror=alert(2)&gt;

首先会被解析为以下DOM树:

1.png

其中

script

标签和

onerror

属性不在白名单规则内,随后将被删除。新的DOM树如下:

2.png

反序列化后如下:

ABC&lt;img src="1"&gt;

理想状态下对输入内容进行过滤后其输出内容都是安全的。

style标签的解析与序列化

Sanitize模块的安全标签列表中包含<style>标签,可以从它入手,因为该标签的处理方式与其它不同。首先,HTML解析器不会解码<style>标签中的HTML实体。举个例子:

&lt;div&gt;I &amp;lt;3 XSS&lt;/div&gt;
&lt;style&gt;I &amp;lt;3 XSS&lt;/style&gt;

生成如下DOM树:

3.png

可以看到,&lt<div>标签中已被HTML解码,但在<style>标签中没有。编码的大致过程为''<>等特殊字符被替换成&"<>。然后,对于一些特定标签比如<style>标签,在反序列化生成新的HTML内容时没有进行HTML实体编码,举个例子:

4.png

反序列化生成的HTML内容为:

&lt;div&gt;I &amp;lt;3 XSS&lt;/div&gt;
&lt;style&gt;I &lt;3 XSS&lt;/style&gt;

可以看到<字符在<div>标签内进行了HTML编码为&lt,但在<style>标签中没有。该特性可被恶意利用,比如如下DOM树:

5.png

其由Sanitize反序列化生成HTML内容为:

&lt;style&gt;&lt;/style&gt;&lt;img src onerror=alert(1)&gt;

这将产生XSS漏洞。接下来的问题是:如何构造出一个恶意的DOM树?

Foreign content特性

HTML规范中有很多有趣的特性,当存在<svg>或者<math>标签时,解析规则会产生变化且上述中<style>标签的两个特性将不再受用,该特性就是:<svg>/<math>标签中的内容会进行HTML实体解码。理想状态下在Sanitize场景下就会生成一个恶意的DOM树举个例子:

&lt;svg&gt;&lt;style&gt;I &amp;lt;3 XSS

对应的DOM树为:

6.png

最终输出为如下并产生XSS漏洞:

&lt;svg&gt;&lt;style&gt;I &amp;lt;3 XSS&lt;/style&gt;&lt;/svg&gt;

漏洞复现

回到主题,如何绕过Sanitize的过滤规则?RELAXED配置场景下,<style>标签允许输入但是<svg>/<math>标签都不行,Sanitize使用的是Google Gumbo解析器,它支持HTML5中的新特性。Sanitize对CSS语法也进行了安全过滤,但是我发现! 使用/**/注释的方法可以进行有效的代码注入,举个例子:

&lt;svg&gt;&lt;style&gt;/*&amp;lt;/style&gt;&amp;lt;img src onerror=alert(1)*/

DOM树如下:

7.png

<svg>标签由于不在白名单中被删除了。但其内容仍然存在,因此,此时的DOM树如下:

8.png

此时已不再需要进行过滤了,因此反序列化生成的HTML代码为:

&lt;style&gt;/*&lt;/style&gt;&lt;img src onerror=alert(1)&gt;*/

好了,XSS已经出来了。

参考链接

https://xz.aliyun.com/t/8226