【Gmail中AMP4Email所导致的XSS漏洞】这篇文章讲述的是我在2019年8月向谷歌报告的XSS漏洞,和Gmail中的AMP4Email有关,这也是被称为DOM Clobbering攻击手法的具体实现 。
什么是AMP4EmailAMP4Email(也称为动态邮件)是Gmail的一个新特性,它能让电子邮件包含动态html内容 。虽然很久以前就能编写含有HTML标记的电子邮件,但这通常只包是静态内容,即某种格式、图像等,不含任何脚本或表单 。而AMP4Email则意味着更进一步,往电子邮件加入了更多的动态内容 。在谷歌官方的一篇文章中,有一个完整的总结:
通过动态电子邮件,你可以很容易地直接对消息本身执行操作,比如回复某个事件、填写问卷、浏览目录或评论等 。以谷歌文档中的评论为例,当某人在评论中提到你时,你就不会收到单独的电子邮件,而是可以直接从消息中回复评论(可以观察到Gmail分出一个线程) 。不过该功能也引出了一些明显的安全问题,最明显的则是XSS 。在电子邮件中插入动态内容,是否意味着我们可以轻松地注入任意JAVAscript代码嘛?不,这其实并不容易 。
AMP4Email有一个强大的验证器,简而言之,就是它有一个强大白名单,限制使用某些HTML标记 。具体情况可以通过https://amp.gmail.dev/playground/进行查看(如下图),你也可以向自己发送一封动态电子邮件,看看它是如何工作的!

文章插图
当你试图添加恶意HTML标签时,会看到一个错误 。

文章插图
而我在尝试使用各种方法来绕过安全限制时,我注意到可以往标签中写入id属性 。

文章插图
这貌似是一个好的切入点,因为创建包含自定义的id属性的HTML元素可能导致DOM Clobbering 。
DOM Clobbering
DOM Clobbering是Web浏览器的一个旧特性,在许多应用中,它都会引起麻烦 。一般来说,当你创建一个元素(例如<input id=username>),然后希望从JavaScript中引用它时,通常会使用document.getElementById('username')或document.querySelector('#username') 。但以上并不是全部的方法!
传统的方法是通过全局window对象的属性来访问它,例如window.username 。所以在以上例子中,这和document.getElementById('username')完全相同!如果此时应用的某些动作完全基于某些全局变量,那么就可能导致DOM Cloberring!
为了进一步分析DOM Clobbering,假设我们有以下javascript代码:
if (window.test1.test2) { eval(''+window.test1.test2)}此时我们的目的是只使用DOM Clobbering技术实现JS代码 。为了做到这件事,我们需要解决以下两个问题:
- 我们知道可以为window创建新属性,那我们可以在其他对象上创建新属性吗(例如test1.test2)?
- 我们可以控制将DOM元素转换成字符串的流程么?大多数HTML元素在转换为字符串时,都会得到类似[object HTMLInputElement]的结果 。
<form id=test1> <input name=test2></form><script> alert(test1.test2); // alerts "[object HTMLInputElement]"</script>而为了解决第二个问题,我编写了一个简短的JS代码,它遍历HTML中所有可能存在的元素,检查它们的toString方法是否继承自object 。如果不是,则可能会返回其他对象 。代码如下:
object.getOwnPropertyNames(window).filter(p => p.match(/Element$/)).map(p => window[p]).filter(p => p && p.prototype && p.prototype.toString !== object.prototype.toString)以上代码返回了两个元素:HTMLAreaElement(<area>)和HTMLAnchorElement(<a>) 。在AMP4Email中,第一个不在白名单,所以只能利用第二个 。而对于<a>,toString函数只返回href属性的值:
<a id=test1 href=https://securitum.com><script> alert(test1); // alerts "https://securitum.com"</script>因此,如果我们想进行攻击,(通过window.test1.test2的值),则需要以下类似代码:
<form id=test1> <a name=test2 href=https://www.isolves.com/it/aq/wl/2019-11-20/"x:alert(1)">但问题是它根本不会生效 。test1.test2是未定义的 。就是把<a>替换为<input>也一样 。
推荐阅读
- 中国国家|为什么说,考上重点高中,非常重要?
- 广东中山现在能不能进2022年1月, 广东中山现在安全吗
- 中国婚庆协会介绍
- 中国婚庆网详细介绍
- 中国李姓排名第几位 姓氏李排名全中国第几
- 虎头蜂种类图片大全最毒的蜂 中国毒蜂种类
- 铁观音中的茶氨酸有什么作用
- 台州首家茶叶品牌获中茶杯金奖
- 中国诗歌万里行走进黑茶之乡,湖南安化
- 阿胶糕粘在容器拿不下来怎么办 做好的阿胶糕怎么从容器中拿出来
