Marginwidth/marginheight – 意想不到的跨源通信通道
2020-08-04 10:48:20 Author: xz.aliyun.com(查看原文) 阅读量:329 收藏

2020年7月6日,我在Twitter上宣布了XSS挑战,到目前为止,只有四个人能够解决它,每个人都告诉我他们以前从未听说过挑战中使用这种"奇特"的方式,因此,这里有一篇文章解释了这个"奇特"以及一些背景故事。

挑战的核心在于以下几行JavaScript:

document.addEventListener("DOMContentLoaded", () => {
    for (let attr of document.body.attributes) {
        eval(attr.value);
    }
});

该代码仅对<body>元素的所有属性进行迭代,并将所有这些属性的值作为JavaScript执行。由于挑战中没有其他源,这意味着要解决该问题,需要找到一种方法来将任意属性值注入document.body。那怎么可能呢?

当我注意到HTML规范中一个有趣的代码片段时,一切就开始了。规范的第14部分称为“渲染”,介绍了某些元素的默认样式。例如,它说<style>or <script>元素默认情况下不显示(即 display:none)。有趣的是<body>的边距是如何确定的?

该表表示,如果<body>标签拥有一个名为marginheight的属性,那么它将映射到该元素的CSS属性——margin-top上。如果不存在该属性,则检查topmargin属性。如果也不存在,那么(接下来就很有意思了),如果当前页面位于嵌套的浏览器上下文(就是说在<frame><iframe>)中,浏览器将使用容器元素的marginwidth属性。这种现象在跨域的时候也一样,这是规范中直接允许的:

起初,我认为这是一个历史遗留问题,并且没有哪个现代浏览器实际以这种方式实现它。

浏览器行为

为了测试浏览器的行为,我有一个简单的代码,可让我检查是否考虑了该marginwidth属性。

<iframe src="https://sekurak.pl/.htaccess" marginwidth="100px"></iframe>

Chromium

在Chromium中,该marginwidth属性反映在<body>元素中,但在赋值之前已被强制转换为整数。有趣的是Chromium会监听此值的更改,因此,如果您动态更改它,它也会反映在iframe中。这是一个例子:

<style>
  iframe, input {
    width:400px;
  }
</style>
<iframe id=ifr src="https://sekurak.pl/.htaccess" marginwidth="0"></iframe>
<br>
<input type=range 
       min=0 
       max=500 
       value=0
       oninput="ifr.setAttribute('marginwidth', this.value)">

Firefox

在Firefox中,的值<iframe marginwidth>根本不会反映在嵌套文档DOM树中。但是已将其考虑在内,可以通过进行检索getComputedStyle()。因此,带有滑块的示例的工作方式与Chromium中的完全相同。

Safari

在Safari中,的值无需任何修改即可<iframe marginwidth>反映在嵌套<body>元素中。

与Firefox和Chromium相反,Safari不会监听属性的更改,因此滑块示例无法使用

挑战解决方案

因此,挑战的解决方案非常简单:

<iframe src="https://securitymb.github.io/xss/3"
        marginwidth="alert(document.domain)">

祝贺@terjanq,@shafigullin,@BenHayak和@steike找到了预期的解决方案!

对于那些试图找到解决方案但没有设法解决的人;提示中说:"使用Safari 可能会稍微好一点"

marginwidth/ marginheight作为跨域通信通道

marginwidth/marginheight的"副作用"就在于让跨域有了可能性,在不同的浏览器中有不同的实现方式:

  • 在Safari中,通过设置父元素的marginwidth,然后在子元素中观察<body>的marginwidth。
  • 在Chrome中,通过在父级中逐字节设置marginwidth,并观察<body marginwidth>子级中的属性改变
  • 在Firefox中,通过在父级中逐字节设置marginwidth,然后在子元素中观察getComputedStyle(document.body).marginLeft。
    我实现了它并托管在https://cdn.sekurak.pl/marginwidth.html:

总结

我认为本文的主要收获是HTML规范仍然包含一些隐藏的"宝石",这在某些晦涩的攻击中是有可能存在的。
另外,我认为这marginwidth特别适合XS泄漏漏洞,但我找不到可行的方案。

作者: Michał Bentkowski
原文地址:https://research.securitum.com/marginwidth-marginheight-the-unexpected-cross-origin-communication-channel/


文章来源: http://xz.aliyun.com/t/8067
如有侵权请联系:admin#unsafe.sh