在上一篇的Edge – 阅读模式下的 SOP 绕过中我们就讨论过阅读模式的SOP绕过了,今天我们继续探索另一个微软Edge的SOP绕过,在滥用data/meta
的情况下,domainless
页面可以自由访问domained
的页面。
如果你不想看这篇文章,你可以看59秒的利用视频Tweeting like Charles Darwin (automatic)和两分钟的Tweeting like Charles Darwin (explained)。
如果你是刚刚学习SOP绕过,请先阅读:SOP bypass / UXSS – Adventures in a Domainless World (Edge)和SOP bypass / UXSS – More Adventures in a Domainless World (IE),文章以下内容是基于相同的思路,只是另一种新手法。
这里我们先了解一个重要的概念:about:blank页面始终是其引荐来源的domain。这意味着twitter’s iframe的about:blank无法访问google’s的空白页面。即使地址之间匹配(about:blank),document.domain
也不同。
以前,我们可以创建about:blanks的domains或者about:blanks的domainless。我们有权限可以访问每个about:blank ,无论其domain是怎样的。例如,假设我们有一个空白domainless在主页面上使一个iframe指向twitter,另一个指向google。那些iframe内有空白的sub-iframes
,它们的domains当然是twitter和google。在这样的情况下,top
窗口可以访问被控制的空白,着意味着访问google和twitter的DOM
。
在以前的时候,上述的场景可以完美的运行起来,但是微软在三月前使用了一个技巧来修补了这个漏洞:空白domainless不再是真正的域名,它们始终设置随机GUID
作为其domain,就像这样: {53394a4f-8c04-46ab-94af-3ab86ffcfd4c}
。但后来有人给我展示了一些更有趣的东西:domain看起来像是blank/empty
,但其实不是,也就是说,Edge将隐藏GUID
并返回空,但在内部,它仍然是GUID
。
让我们一起来试试。启用Edge的DevTools enabled(F12)
,并在地址栏中输入about:blank。这用于创建一个空白的domainless,它可能看起来没有什么变化,但这只是Edge给我们展示的一些小把戏罢了。我们可以慢慢的欣赏它,因为我们又足够的时间来绕过这个问题。
在这里我们可以看到,DevTools
认为我们在一个空白的domain中,但它不是。
如果连DevTools
的检测都是这样,我们怎样能看到这究竟发生了什么呢?其实很容易,只要尝试加载任何具有相对路径的文件,或者改变这个窗口的位置,甚至直接document.write
就可以揭开这个小把戏了。让我们使用location.href = 1
看看会发生什么。
我们以前的创建空白domainless的漏洞已经修补了。在这里,我们我们使用Flash/GetURL
,在主(top)窗口上设置一个uri数据。但问题关键是补丁已经打上了,而且更糟的是,我们不能自动运行Flash了!在Windows Creators Update
上Edge会在执行Flash之前发出请求许可。
看看以前的漏洞,以前文章中的PoCs现在看起来是多么的丑陋啊!如果你和我们一样想减少SOP中的攻击面,你可以和我们联系。
我们已有的top的data:uri 已经不再起作用了,那我们怎样去克服呢?首先,我现在开始玩iframe而不是top,因为正如我们在以前看到那样,Edge其实不喜欢data:uris在主窗口。
top.location.href = "data:text/html,SOMETHING"; // Fails badly, error page
但是设置一个data:uri作为iframe的位置很好。但是,这不是一个bug,而是在top隔离了iframe domain
而已。
正如我们在SOP阅读器模式中所看到的那样,data:uri“隔离”限制时是微不足道的(只要一个self document.write
就可以访问来源了),但我们现在不行这样。访问top现在没有任何意义,我们需要的是获得一个空白domainless的方法。为此,我们需要将它们三合一: data-meta-data
。这可以使Edge把我们需要返回的东西返回给我们。
具体来说,我们将使用一个data uri来设置iframe的位置,该data uri会显示重定向到另一个data uri中。那一刻,无论是谁都会在Edge上迷路。
创建空白domainless方法:
现在我们来构建一个URL,将一个常规(domained)iframe转换为一个domainless。如果我在我的脑海里不停重复“data-meta-data”,这对我来说更容易,因为在现实中,这就是全部。
我知道它不如E = mc2
那么美丽,但是我们的这个技巧可以用来窃取其他人(包括爱因斯坦)的凭据,电子邮件,paypal账户,甚至用他的名字发短信。让我们先测试一下我们所学到的东西,直到这一点真的有效的被实现了。如果我们会玩bing.com这是很容易的,因为它有一个内部的空白iframe,它不使用XFO。
我们将创建一个带有两个框架的网页:一个是bing.com和一个domainless。在domainless中,我们可以在bing的内部空白iframe中执行代码。Bing imager
非常适合我们的测试。你也可以打开Chrome,和我一起来测试。
这很好,现在我们将借助我们的domainless data-meta-data
来构建该页面,并且将代码注入到空白的iframe中。这里我有些话没有说出来,你还记得我们在原始domainless SOP中与nature.com的命名问题吗?如果不记得,你可以先去快速的看一遍。
在这一点上,我们的domainless能够访问bing的空白,但访问机制是非常重要的。我们不能直接访问DOM
,我们必须使用window.open
方法。换句话说,如果bing位于主页面的第一个iframe中,我们将无法以这种方式访问其内部iframe:
alert(top[0][0].document.cookie); // ACCESS DENIED
我们甚至不能这样做:
top[0][0].location.href = "javascript:alert(document.cookie)"; // ACCESS DENIED
那么我们该怎么办呢?很容易,在一个窗口中打开一个javascript url
和iframe
的名称。如果bing的内部iframe名称是“ INNER_IFRAME
”,以下代码就可以很好的运行了:
window.open("javascript:alert(document.cookie)", "INNER_IFRAME"); // SOP BYPASSED!
但是问题来了!Bing中嵌套的iframe没有名字!不过不用惊慌,我们可以要求Bing团队为我们设置一个名称,或者我们可以继续pushing。继续更好的pushing!
我们不能设置我们不拥有的iframe的名称,除非它与我们在同一个domain中。我们要渲染一个内部有空白的iframe。外部iframe位于不同的domain上,但标签本身(元素,对象)位于我们的domain中,因此我们可以设置我们想要的任何名称。
<iframe name="ANY_NAME" src="http://bing.com"> <iframe src="about:blank"></iframe> </iframe>
但是内部iframe是通过bing渲染的,即使它是空白的,它的domain仍然是bing.com。更改其名称的唯一方法是首先将其位置设置为我们可以访问的位置,然后才能更改其名称。现在,如果我们想改变about:blank的位置,我们就需要成为bing.com,所以我们以后可以访问空白domainless 。
记住:我们的目标是从空白domainless访问到一个domained。如果我们将domain设置为我们所匹配的,那么访问它是没有意义的!所以这里是我们将要做的是:我们将设置位置,更改iframe名称,然后以这样的方式恢复位置,使其保持原始domain。听起来很复杂?
设置为an x-domain-iframe的名称:
现在,内部iframe有一个名字,它的域恢复到bing.com!这是代码:
// Sets the location of Bing's inner iframe to about:blank // But now it is in our domain so we can set a name to it. window[0][0].location = "about:blank"; // Set the inner iframe name to "CHARLES" so we can later inject code // using a window.open("javascript:[...]","CHARLES"); window[0][0].name = "CHARLES"; // Restore Bing's domain to the about:blank that we've just renamed. window[0][0].document.write('<meta http-equiv="refresh" content="0;url=about:blank">'); window[0][0].document.close();
让我给你一个好消息:我们真的不需要网站“about:blank” iframes,因为我们可以像上面那样做。换句话说,如果bing的内部iframe是about:blank并不是因为我们最终将它设置为空的原始domain!
现在应该可以了。我们可以从我们的data-meta-data
iframe中运行window.open
:
window.open("javascript:alert(document.cookie)", "CHARLES"); // Fireeeeeeeeeee!!!
关于PoC,bug hunter有一个重要事项:在上面的示例中,我们使用http(不安全)连接,因为在https(安全)中,数据的meta refresh
被阻止,所以它不会重定向到最终的数据uri。Edge错误地认为重定向是不安全的。然而,这可以通过使用document.write
而不是第一个data uri来轻松绕过。所以代替data-meta-data
应该是document.write
(meta-data)。说得通?
我们没有在上述的PoC中使用它,因为在进行演示交互时(让你按下按钮来运行它)Edge non-exploitable崩溃了三分之一的时间。所以,我选择在http和https中使用自动可控制的和可靠的PoC。但是无论如何,如下所示,它并不重要:我们的不安全(http)空白domainless能够访问安全页面,所以这里我们建立了一个真实的例子。
我们这里建立一个假设,查尔斯知道黑客的存在,所以他以十分偏执的模式使用他的电脑:他从来没有打开过他的Gmail,Twitter和个人文档中的跳转链接。
这是他正在任务栏上打开一个新的InPrivate
窗口!
他的心情很好,直到他用Twitter的账号打开了另一个标签,并为阿尔弗雷德·华莱士(Alfred Wallace)提供了一些关于谁先发布的信息。
几分钟后,华莱士的回应就包括了支持他的声明的证据。但是请记住,查尔斯不信任何人,所以他复制了链接,并将其粘贴到一个新的窗口中,远离他拥有个人数据(gmail,twitter)的窗口。
在这里什么可以出现不小心的错误?一切!Twitter有几个iframe,就像世界上大多数网站一样。其实它有两个命名about:blank的iframe,所以这应该比Bing更容易!但在回到我们的故事之前,我们列举twitter的iframe使用DevTools
找到一个很好的候选人。我在这里打开一个不同的窗口,与查尔斯会话无关。
很好!dm-post-iframe
看起来不错,所以我们拥有了我们需要接管查理的帐户。
查尔斯打开了一个新的私人窗口,并加载了华莱士给他的网址。他不知道的是,即使在私人的浏览器窗口,也可以相互通信。那么,如果我们在domainless iframe
中执行下面的代码,会发生什么?
window.open("javascript:alert(document.cookie)", "dm-post-iframe");
你是完全正确的,我们现在拥有了查尔斯·达尔文的cookies
。
警告:以上的概念证明只是提醒(仅在你的屏幕上显示)你要注意Twitter Cookie
的安全。
请记住,我们真的不需要InPrivate
窗口。上面的例子只是说明在一个偏执用户的情景下是怎样发生攻击的,但通常情况下更容易,因为人们点击链接,而不用完成Charles所做的所有工作来防止攻击。此外,考虑到攻击者使用恶意软件,将其坏的位置从流行网站的廉价横幅中部署出来。如果一个攻击者把攻击托管在雅虎横幅内,用户登录到她的Twitter帐户,用户和攻击者之间就不会拥有任何互动,而攻击者就已经拥有了用户的Twitter cookie
。
在像查尔斯·达尔文这样的推特中,我们建立了一个更好的PoC。我们将以他的名字发短信,甚至尝试抓住他的密码,而不是阅读他的cookies。其实大多数用户(如查理)都使用自动填写密码的密码管理员。Edge密码管理器没有什么不同,所以如果查尔斯保存了他的密码,我们就可以得到它。这不是很难,只是强迫他注销,登录页面将被自动加载,其所有的数据(用户名和密码)保存到我们的银色的播放器中。事实上,在这种情况下,除非用户进行交互,否则窗体是隐藏的,但是Edge会自动填充它,所以我们甚至不必使窗体可见。
在运行PoC之前,请考虑这是你的帐户,请不要攻击其他人并用于其他非法用途,一切责任请自行负责。如果你没有使用自动填充密码,而是每次都自己输入,请注意你身后是否有人,她可以在一个常规警报对话框中看到你的密码。小心!
我想到的快速问题:
我们可以在网站中使用这个吗?空白iframe? 当然!我们甚至可以在没有iframe的网站上进行。请阅读这两篇文章,在其中注入一个不同来源的iframe。同样在Internet Explorer上的SOP绕过。
在Facebook上可以做同样的事情吗? 我没有Facebook帐户,所以我没有测试。但我相信SOP旁路能够访问地球上的每一个domain ,Period。这可能会有点难度,但请更加努力。
这在其他浏览器中有效吗? 我没有尝试其他浏览器,但显然应该是可以的。UXSS / SOP旁路往往在每个浏览器都存在的。
漏洞利用代码很简单。你可以把它打开看一看,如果你有任何疑问,可以在我的twitter上留言!
祝你今天愉快!
*作者:brokenbrowser,