通过id获取input标签元素对象_学点新姿势: 通过DOM Clobbering 引发GMail的的XSS

3b766286b22a58e081d4971aed5c1f4e.png

什么是AMP4Email

AMP4Email(也称为动态邮件)是Gmail的一项新功能,可使电子邮件包含动态HTML内容。尽管编写包含HTML标签的电子邮件已经存在了很多年,但通常情况下都是假定HTML只包含静态内容,即某种格式,和一些图像等,而没有任何脚本形式的存在。AMP4Email应该算是创新的更进了一层,它允许编写包含HTML标签的电子邮件并允许电子邮件中包含动态内容。在Google官方G Suite博客的一篇文章中,很好地总结了动态邮件的一些使用案例:

借助动态电子邮件,您可以轻松地直接从邮件内部直接采取行动,例如对事件进行RSVP,填写调查表,浏览目录或回复评论。
以在Google文档中进行评论为例。现在,您将不再在某人在评论中提及您时接收到单独的电子邮件通知,而是会在Gmail中看到一个最新的主题,您可以从该主题中轻松地回复或解决该评论。

该功能提出之后带来了一些明显的安全性问题。最重要的一个可能便是:跨站点脚本(XSS)攻击。如果我们允许电子邮件中包含动态内容,那这是否意味着我们可以轻松地注入任意JavaScript代码呢?

好吧–并不是;并没那么简单进行注入。

简单来说,AMP4Email具有强大的验证器,它是一种在动态邮件中规定允许使用的标记和属性的非常强大的白名单。您可以在https://amp.gmail.dev/playground/上使用它,也可以在其中向自己发送动态电子邮件,以查看其工作原理!

7c0297cb0f64e186022057632033d744.png
图一 AMP4Email动态电子邮件使用截图

如果您尝试向其中添加程序未明确允许的可使用的任何HTML元素或属性,则会收到报错消息。

a146ae9b581866747a6bf52e9cae63e9.png
图2. AMP Validator禁止任意脚本标签

在使用AMP4Email并尝试各种方法绕过它时,我注意到该属性下ID并没有被限制使用(图3)。

9786e8002a6de12d2076d7be3f47e730.png
图3. id不允许属性

这看起来像是可以被入手进行分析的好地方,因为创建具有用户控制id属性的HTML元素这可能会导致DOM Clobbering。

DOM Clobbering

DOM Clobbering是Web浏览器的遗留功能,只会在许多应用程序中引起麻烦。通常情况下,当您使用HTML创建一个元素(例如<input id=username>),然后又希望从JavaScript引用该元素时,开发者通常会使用document.getElementById('username')或document.querySelector('#username')之类的函数进行调用。但这并不是唯一的方法!

老式方法下还能通过全局window对象的属性访问它。因此会使用window.username函数,在这种情况下此函数与document.getElementById('username')效果完全相同!如果应用程序基于某些全局变量的存在来做出决定,则此行为(称为DOM Cloberring)可能导致有趣的漏洞(想象一下:)if (window.isAdmin) { ... }。

为了进一步分析DOM Cloberring,假设我们有以下JavaScript代码:

if 

我们的工作是使用DOM Cloberring技术评估任意JS代码。要解决任务,我们需要找到两个问题的解决方案

  1. 我们知道我们可以在前面创建新属性window,但是我们可以在其他对象上创建新的属性吗(类似于test1.test2)?
  2. 我们可以控制将DOM元素转换为字符串的方式吗?大多数HTML元素在转换为字符串后,都会返回类似于于这样的内容[object HTMLInputElement]。

让我们从第一个问题开始。解决这个问题最常用的方法是使用<form>标签。标签内的每个<input>均添加一个属性name,该属性等同于在<form>增加一个属性值。参考以下示例:

<

为了解决第二个问题,我创建了一个简短的JS代码,该代码会对HTML中所有可能的元素进行迭代,并检查它们的toString方法是继承Object.prototype还是以其他方式来定义。如果他们不是继承自Object.prototype,则[object SomeElement]可能会返回其他东西。

Object

代码返回了两个元素:HTMLAreaElement(<area>)和HTMLAnchorElement(<a>)。AMP4Email中不允许使用第一个,因此我们只关注第二个。如果是<a>element,则toString仅返回hrefattribute 的值。参考以下示例:

<

在这一点上,如果我们想解决原始问题(即window.test1.test2通过DOM Clobbering 评估值),则需要类似于以下代码:

<

但问题是它根本不起作用。test1.test2会是undefined。尽管<input>元素确实成为了<form>的属性,但同样的事情并没有发生在<a>。

但是,有一个有趣的解决方案可以在基于WebKit和Blink的浏览器中使用。假设我们有两个相同的元素id:

<

那么访问时我们将得到什么window.test1呢?我直觉上希望得到具有该ID的第一个元素(document.getElementById('#test1')。但是,在Chromium中,我们实际上得到了一个HTMLCollection!

c1a69f5c1158deaeb3231e59acc8ff85.png
图4. window.test1指向HTMLCollection

在图4里我们可以发现一个很有趣的地方,我们可以通过索引访问该特定元素HTMLCollection(像示例中的0和1),还有ID。这意味着window.test1.test1实际上是指第一个元素。

事实证明,setting name属性还创建了新属性HTMLCollection。现在我们有了以下代码:

<

我们可以通过访问第二个锚元素window.test1.test2来获得内容。

8b3885f32adadc05187c7201040ec2f5.png
图5.我们可以window.test1.test2定义

因此,回到eval(''+window.test1.test2)我们可以通过DOM Clobbering进行利用,解决方案将是:

<

现在让我们回到AMP4Email,看看我们可以如何在实际案例中利用DOM Clobbering。

在AMP4Email中利用DOM Clobbering

我已经提到过,我可以通过将自己的id属性添加到元素,AMP4Email可能容易受到DOM Clobbering的影响。为了找到可利用的条件,我决定看一下的属性window(图6)。立即引起注意的是AMP。

b189ce85918ce8a3a02219ae2fc80bf3.png
图6. window全局对象的属性

在这一点上,事实证明AMP4Email实际上对DOM Clobbering采取了某种保护措施,因为它严格禁止id属性的某些值,例如:(AMP图7)。

d8185e77e72a26823fc409be8c62deb0.png
图7. AMP是idAMP4Email中的无效值

但是,没有限制AMP_MODE。所以我准备了一个代码,<a id=AMP_MODE>只是为了看看会发生什么……

…然后我注意到控制台中有一个非常有趣的错误(图8)。

175e618370fd2a54f9a8982346587cb7.png
图8. 404加载某些JS文件

如图8所示,AMP4Email尝试加载某些JS文件,但由于404而未能加载。然而,特别引人注目是URL中间部分的undefined。我想出一个可能的解释,:AMP尝试获取属性并将其放在URL中。由于DOM Clobbering,因此缺少了预期的属性。便出现了包含undefined代码的链接如下所示:

https://cdn.ampproject.org/rtv/undefined/v0/amp-auto-lightbox-0.1.jsAMP_MODEundefined

f

尽管阅读起来并不特别困难,但下面显示了手动去混淆的代码形式(为清楚起见,省略了某些部分):

var 

在第1行中,代码创建了一个新script元素。然后,检查AMP_MODE.test和window.testLocation是否都是真实的。如果它们AMP_MODE.localDev是正确的(也是第11行),则将window.testLocation其用作生成脚本URL的基础。然后,在第17和18行中,将其他一些属性串联起来以形成完整的URL。尽管乍一看可能并不明显,但是由于代码的编写方式以及DOM Clobbering,我们实际上可以控制完整的URL。让我们假设AMP_MODE.localDev和AMP_MODE.test都是真实的,看代码如何进一步简化:

var 

您还记得我们之前window.test1.test2使用DOM Clobbering 超载的练习吗?现在我们需要做同样的事情,只是需要超载window.testLocation.protocol。因此,最终的有效的payload为:

<!-- 

实际上,由于在AMP中部署了Content-Security-Policy[1],因此在实际情况下该代码未执行:

Content

我没有找到绕过CSP的方法,但是当尝试这样做时,我发现了绕过基于目录的CSP的一种有趣的方法,然后我在推特上发了信息(后来发现,在CTF中已经使用了相同的技巧在2016年[2])。Google在其漏洞赏金计划中,实际上并不期望绕过CSP并支付全部赏金。仍然是一个有趣的挑战。也许其他人会找到绕过的方法

在帖子中,我已经展示了如果满足某些条件,如何使用DOM Clobbering执行XSS。这肯定是一个有趣的旅程!如果您想玩这些XSS-es,请看看我的XSS Challenge,它是基于这种XSS的。

原文链接: https:// research.securitum.com/ xss-in-amp4email-dom-clobbering/

今天的内容就分享到这里,希望对你有所帮助。最近二向箔安全推出了漏洞挖掘实战班,小白入门到挖洞大佬,如果你也想学习漏洞挖掘并获得一定的报酬奖励,现在马上扫码上车。

487d7839733a35555ae385211bbd2567.png

参考

  1. ^CSP指的是内容安全策略,为了缓解很大一部分潜在的跨站脚本问题,浏览器的扩展程序系统引入了内容安全策略(CSP)的一般概念。这将引入一些相当严格的策略,会使扩展程序在默认情况下更加安全,开发者可以创建并强制应用一些规则,管理网站允许加载的内容。
  2. ^https://blog.0daylabs.com/2016/09/09/bypassing-csp/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值