mXSS:隐藏在代码中的漏洞

mXSS:隐藏在代码中的漏洞

Ots安全 2024-06-02 12:20

跨站点脚本 (XSS) 是一种众所周知的漏洞类型,攻击者可以将 JavaScript 代码注入易受攻击的页面。当不知情的受害者访问该页面时,注入的代码将在受害者的会话中执行。此攻击的影响可能因应用程序而异,但不会造成业务影响,例如帐户接管(ATO)、数据泄露,甚至远程代码执行(RCE)。 

XSS 有多种类型,例如反射型、存储型和通用型。但近年来,XSS 的变异类型因绕过 DOMPurify、Mozilla bleach、Google Caja 等清理程序而令人生畏……影响了包括 Google 搜索在内的众多应用程序。到目前为止,我们发现许多应用程序都容易受到此类攻击。

但是 mXSS 是什么? 

(我们还在 Insomnihack 2024 演讲中探讨了这个主题:击败 Sanitizer:为什么你应该将 mXSS 添加到你的工具箱中。)

背景

如果您是 Web 开发人员,您可能已经集成甚至实施了某种清理措施来保护您的应用程序免受 XSS 攻击。但人们对制作合适的 HTML 清理程序有多难知之甚少。HTML 清理程序的目标是确保用户生成的内容(例如文本输入或从外部来源获取的数据)不会带来任何安全风险或破坏网站或应用程序的预期功能。

实施 HTML 清理程序的主要挑战之一在于 HTML 本身的复杂性。HTML 是一种多功能语言,具有各种元素、属性和潜在组合,这些元素、属性和组合可能会影响网页的结构和行为。准确解析和分析 HTML 代码并保留其预期功能可能是一项艰巨的任务。

HTML

在讨论 mXSS 之前,我们先来了解一下 HTML,它是网页的基础标记语言。了解 HTML 的结构及其工作原理至关重要,因为 mXSS(突变跨站点脚本)攻击利用了 HTML 的怪癖和复杂性。

HTML 被认为是一种宽容的语言,因为它在遇到错误或意外代码时具有宽容的特性。与一些更严格的编程语言不同,即使代码编写得不完美,HTML 也会优先显示内容。这种宽容的表现如下:

当呈现损坏的标记时,浏览器不会崩溃或显示错误消息,而是会尝试尽可能地解释和修复 HTML,即使其中包含轻微的语法错误或缺少元素。例如,在浏览器中打开以下标记

test将按预期执行,尽管缺少结束p标记。查看最终页面的 HTML 代码时,我们可以看到解析器修复了损坏的标记并
p自行关闭了元素:

test

它为何具有宽容度:
– 可访问性:网络应该对所有人都开放,HTML 中的小错误不应妨碍用户查看内容。宽容度允许更广泛的用户和开发人员与网络互动。

– 灵活性:HTML 经常被具有不同编码经验水平的人们使用。容忍度允许一些粗心或错误,而不会完全破坏页面的功能。

– 向后兼容性:网络在不断发展,但许多现有网站都是使用较旧的 HTML 标准构建的。即使这些较旧的网站不符合最新规范,Tolerance 也能确保它们仍可在现代浏览器中显示。

但是我们的 HTML 解析器如何 知道 以何种方式“修复”损坏的标记?应该
变成
还是

为了回答这个问题,有一个文档齐全的HTML 规范,但不幸的是,仍然存在一些歧义,导致即使在当今的主流浏览器之间也存在不同的 HTML 解析行为。

突变

好的,那么 HTML 可以容忍损坏的标记,这有什么关系呢? 

mXSS 中的 M 代表“变异”,HTML 中的变异是由于某种原因对标记所做的任何类型的改变。
– 当解析器修复损坏的标记(

test
→ 

test

)时,这就是一次变异。 

– 规范化属性引号(
→ 
),这是一种变异。

– 重新排列元素(


→ 

),这是一个突变

– 等等…

mXSS 利用这种行为来绕过清理,我们将在技术细节中展示示例。

HTML 解析背景

将长达 1500 多页的 HTML 解析标准总结为一个章节是不现实的。但是,由于它对于深入理解 mXSS 以及有效载荷的工作原理非常重要,我们必须至少涵盖一些主要主题。为了简化操作,我们开发了一个mXSS 速查表(稍后将在本博客中介绍),将这个繁琐的标准浓缩为研究人员和开发人员更易于管理的资源。

不同的内容解析类型

HTML 并不是一个通用的解析环境。元素以不同的方式处理其内容,有七种不同的解析模式。我们将探索这些模式,以了解它们如何影响 mXSS 漏洞:
– 空元素

area, base, br, col, embed, hr, img, input, link, meta, source, track, wbr
– 元素template

template
– 原始文本元素

script, style, noscript, xmp, iframe, noembed, noframes
– 可转义的原始文本元素

textarea, title
– 外来内容元素

svg, math
– 明文状态

plaintext
– 普通元素

All other allowed HTML elements are normal elements.

我们可以使用以下示例相当容易地展示解析类型之间的区别:

1、我们的第一个输入是一个div元素,它是一个“普通元素”元素:

">

查看解析后的标记,我们可以清楚地看到解析的差异:

![](https://mmbiz.qpic.cn/sz_mmbiz_png/rWGOWg48taeSHu8XGicDJF2v3TblZWxck7micb3JLaguYBVDV6dKnrwxYVV7R9bqyfxyIF8V6EGe7WIoCNm3YibHg/640?wx_fmt=png&from=appmsg "")

![](https://mmbiz.qpic.cn/sz_mmbiz_png/rWGOWg48taeSHu8XGicDJF2v3TblZWxcksgfibmWrVXaJm3skf3Z67939Kmces57IHZyaxocxUy3KLA8Ujq4eTTw/640?wx_fmt=png&from=appmsg "")

元素的内容div被渲染为 HTML,a元素就创建了。看似结束符div和img标签的东西实际上是元素的属性值a,因此被渲染为元素alt的文本a而不是 HTML 标记。在style示例中,元素的内容style被渲染为原始文本,因此没有a创建任何元素,所谓的属性现在是正常的 HTML 标记。

外来内容元素

HTML5 引入了在网页中集成专门内容的新方法。两个关键示例是元素。这些元素利用不同的命名空间,这意味着它们遵循与标准 HTML 不同的解析规则。了解这些不同的解析规则对于减轻与 mXSS 攻击相关的潜在安全风险至关重要。

让我们看一下与之前相同的例子,但这次封装在一个svg元素内:

<svg><style><a alt="</style><img src=x onerror=alert(1)>">

![](https://mmbiz.qpic.cn/sz_mmbiz_png/rWGOWg48taeSHu8XGicDJF2v3TblZWxckuic9MksCVibzEWV1aXt0uPM6icKOlpG12zGOwWoribK88I57rwhtcYJexA/640?wx_fmt=png&from=appmsg "")

在这种情况下,我们确实看到a创建了一个元素。该style元素不遵循“原始文本”解析规则,因为它位于不同的命名空间内。当位于 SVG 或 MathML 命名空间内时,解析规则会发生变化,不再遵循 HTML 语言。

使用命名空间混淆技术(例如DOMPurify 2.0.0 绕过),攻击者可以操纵清理器,以不同于浏览器最终呈现内容的方式解析内容,从而逃避对恶意元素的检测。

从突变到脆弱性

在涵盖各种杀毒绕过时,mXSS 术语通常被广泛使用。为了更好地理解,我们将通用术语“mXSS”分为 4 个不同的子类别

解析器差异

虽然解析器差异可以称为通常的清理器绕过,但有时它被称为 mXSS。无论哪种方式,攻击者都可以利用清理器算法与渲染器(例如浏览器)算法之间的解析器不匹配。由于 HTML 解析的复杂性,存在解析差异并不一定意味着一个解析器是错误的而另一个是正确的。 

让我们以noscript元素为例,它的解析规则是:“如果启用了脚本标志,则将标记器切换到RAWTEXT 状态。否则,将标记器保持在数据状态。”(链接)这意味着,根据 JavaScript 是禁用还是启用,元素主体的noscript呈现方式不同。逻辑上,JavaScript 不会在清理器阶段启用,但会在渲染器中启用。从定义上讲,这种行为并没有错,但可能会导致绕过,例如: