0x00介绍:
AMP 最常用作开发 Web 上快速加载内容的框架。
作为 AMP 的项目之一,AMP4Email 近年来已被许多领先的邮件服务用作提供动态电子邮件(本质上是常规 HTML 的子集,带有一些默认组件来处理布局、模板、表单等)的一种方式。
Gmail 具有出色的设置,您可以通过其 Playground 网站轻松编写和验证您的 AMP 电子邮件。甚至将其发送到您的邮箱以查看它在 Gmail 中的呈现方式,非常适合安全研究。
当我尝试将这些向量中的任何一个发送到 Gmail 时,我很快发现要么有第二个过滤器在起作用,要么是一个完全不同的 AMP 版本,有另外的安全验证。
在这篇文章中,我将介绍如何设法让其中一个初始向量绕过安全验证并到达我的收件箱。
多年来,我发现绕过 XSS 过滤器的最简单方法是将其诱骗到与浏览器实际用于渲染给定代码段不同的渲染上下文中。
方式有很多种,包括Templates, SVG, Math, CSS等。
在 AMP4Email 的范围内,大多数都是被禁止的,而我唯一真正的选择之一是样式表,所以我决定将我的研究重点放在它上面。
为了使我的攻击起作用,我需要找到过滤器如何呈现样式表与浏览器如何呈现之间的差异。
这意味着要么欺骗过滤器相信假样式标签(打开或关闭)是真实的,并且应该被视为真实的,而实际上浏览器会忽略它。或者恰恰相反,将真正的标签视为假的并忽略它。
正如我上面提到的,我已经有一个向量成功触发了 AMP playground中的 XSS,但无法绕过 Gmail 的过滤器。
<style amp-custom>body{color:red}</styleX>
<meta name="</style><img src='x'onerror=alert(1)">
这个向量起作用的原因是 AMP一旦遇到字符串“</ style ”就离开 CSS 上下文,即使它没有右括号“>”或至少后面没有空格。我认为这是为了减轻其他攻击。但是我能够使用它来欺骗过滤器,让过滤器相信我们回到了 HTML 上下文中,而浏览器显然完全忽略了 </ styleX > 并且很好地保持在 CSS 的范围内。
接下来,我选择了 < meta > 标签的name属性,但任何安全属性都可以在这里使用。但是当浏览器(此时仍然渲染 CSS)遇到这个标签时,它会将其视为格式错误的 CSS,在真正的 </ style > 标签处终止样式表并渲染带有其onerror属性的 < img > 标签,从而触发 XSS。但是,如果尝试将payload发送到 Gmail,则无法加载整个文档。(当过滤器遇到严重的验证错误时会发生这种情况)
<style>div{font-family:'aa/*f<br> ff*/'}</style>
<style>div{font-family:'aa/*f</xxx> ff*/'}</style>
<style>div{font-family:'aa/*f</style> ff*/'}</style>
我很快发现,虽然 AMP 允许在这个字符串-注释混合体中出现任何值,但 Gmail 不允许。
前两个有效载荷一切正常,它们到达我的收件箱时只做了一个小的改动,它们被逃脱了。
<style>div{font-family:'aa/*f</xxx> ff*/'}</style>
转化成
<style>div{font-family:'aa/*f\00003c/xxx\00003e ff*/'}</style>
而且由于我无法在没有 HTML 实体的情况下终止标签('<' , '>') 在 AMP 中看起来还可以,但在 Gmail 中却无法使用。
如果我们将以下负载发送到 Gmail
<style amp-custom>[id='a<br>aa'],body{font-family:'aaaa'}</style>
我们得到完全相同的东西,没有转义或其他突变发生
我在 AMP playground编辑器中将其写下来,却立即收到错误消息。
AMP 将其检测为格式错误的 CSS。
0x02开发Payload:
由于除了选择器之外,所有其他 CSS 上下文都对我的 HTML 实体进行了编码,如果我将编码选择器发送到 Gmail,会发生什么情况?它会为我解码吗?
我再次开始使用我能想到的最安全的payload,只是为了确保如果它确实被过滤,那将是因为编码而不是其他原因。
所以我发送了以下代码段:
<style amp-custom>[id='a<b\000072> aa'],body{font-family:'aaaa'}</style>
是的!有效!Gmail 实际上将 \000072 解码为字母“r”
现在进行真正的测试。我可以使用它来注入结束样式标签吗?
<style amp-custom>[id='a</st\000079le> aa'],body{font-family:'aaaa'}</style>
结果为
为了将所有内容联系在一起,我提出了以下最终有效载荷,它注入了一个 <img> 标记,但此时,可以使用任何 HTML:
<style amp-custom>[id='</st\000079le></head><body> <img src=https://bla.com/xx.jpg onerror=a=1>']{color:blue}</style>
当我打开电子邮件并注意到损坏的图像时,成功了。
按住F12,查看开发工具,发现代码已被加载。
推荐阅读: