本文讲的是
如何绕过sop执行XSS盗取cookie并发送推文?,
先通过视频看看这个漏洞的威力吧,在第一个59秒的视频中,我们使用用户名为:Charles Darwin发送推文。在第二个两分钟的视频中,我们通过Edge默认密码管理器进行发送推文甚至查看用户密码。Charles Darwin就是一个例子,这个漏洞允许攻击者在已经登录twitter的页面上进行关注,甚至产生更大的危害。
视频一:https://youtu.be/K3Ui3JxZGnE
视频二:https://youtu.be/PlxQBmLrnQA
如果你第一次了解sop绕过技术,建议你阅读之前两篇文章:Edge中无域页面进行绕过以及IE中无域页面绕过sop,在这篇文章中,使用了相同的想法,只是采用了不同的技术进行绕过。
先让我们快速的了解一个重要的概念:about:blank页面总是属于它来源的那个域。比如你在twitter页面的iframe标签就不可以访问属于google域中的about:blank页面。即使他们的名称都是about:blank,但是他们输出的document.domain是不同的。
在之前,我们已经创造出了无域的about:blanks页面。这些无域的页面可以访问任何域中的about:blank页面。比如我们在拥有一个主页面的about:blank,并且产生一个iframe指向twitter,另外一个指向google。这些iframe里面有一些空的子iframe,以及他们的域是twitter和google。所以在这种情况下,iframe的最顶端就可以访问域中的页面,也就是可以进入到google以及twitter的域中。
上述情况非常好,但是微软三个月前使用非常聪明的技巧修复了这个漏洞:无域about:blank页面不再是真正的域,微软为它们设置一个随机GUID作为域,如下所示:{53394a4f-8c04-
46ab-94af-3ab86ffcfd4c}。还有一些更有趣的东西(提示给边缘开发者):域将看起来好像是空白,但不是。换句话说,Edge将GUID隐藏并返回空,但在内部,它仍然是GUID。
那就让我们来试试吧,在Edege中按下F12打开调试器,然后在地址栏输入about:blank。这一步骤是用于产生一个无域的页面,现在看起来好像它和之前没有任何变化。但是Edge正在对我们作出防范。不过这对我们来说很轻易的就可以绕过~
我们可以看到,调试工具认为我们在一个空的域,但我们并不是。
绕过补丁,创造无域页面
就连调试工具都被微软的补丁所欺骗,那我们应该如何才能看到这里到底发生了什么改变呢?比预期的更容易,只要尝试加载任何具有相对路径的东西,或者改变这个窗口的位置,甚至使用document.write就可以发现这里改变了什么,让我们使用location.href=1,看看会发生什么?
data:uri方法被修复以及Flash没有开启
我们之前创造无域的about:blank页面的方法已经被修复。我们之前是在最顶层的窗口中使用data:uri。不过这个小伎俩已经被微软修补,甚至现在已经不能自动执行flash插件。在微软最近的更新后,每次执行flash之前,Edge都会对用户进行询问。
现在看起来,之前的POC(http://unsafe.cracking.com.ar/demos/edge-domainless-uxss/bing/index.html)看起来很丑。为Edge团队修复这一漏洞点赞。
发现新的无域页面
我们的data:uri的方法已经对这个攻击不起作用了,那么我们应该如何克服这一困难呢?首先,我将矛头指向了iframe标签, 而不是之前的顶部页面,因为就像我们之前看到的那样,Edge会将在主页面的data:uri拦截。
top.location.href = "data:text/html,SOMETHING"; // Fails badly, error page
但是设置一个data:uri作为iframe的位置很好。但是,这不是一个漏洞,而是从顶部隔离了iframe域。
正如我们在SOP阅读模式绕过这篇文章看到的,data:uri的隔离限制是非常琐碎的,只是一个document.write就可以访问到父级,但是我们现在不想这么做了。因为访问父级顶部对我们来讲并没有多大的作用了。我们现在想得一种方法是得到一个无域的页面,所以我们需要一个三重的组合:数据-元-数据。这将会让Edge返回我们想要的结果。
具体来说,我们将使用一个data:uri来设置iframe的位置,这个data:uri会重定向到另外一个data:uri进行刷新。获取无域页面步骤如下:
通过这一点小伎俩,我们就可以盗取Einsteins凭证,邮箱,paypal账户,设置以他的用户名发推文。让我们首先测试一下我们之前做的攻击是否成功。我们在bing.com进行测试,很简单的就进行了绕过,因为他有一个内部空白的Iframe,以及它没有使用XFO。
攻击预热:测试bing.com
我们将创建一个带有两个iframe的网页:一个指向bing.com和一个指向无域页面。从无域页面进行攻击,我们可以在bing的内部空白iframe中执行代码。 Bing中图片的选项是我们需要的解释模型。让我打开Chrome一秒钟,告诉你我的意思。
现在我们将借助我们的无域”数据-元-数据”来构建该页面并将代码注入到空白iframe中。但是有一些我没有说的话,你还记得我们在原始的无域SOP中与nature.com的命名问题吗?如果没有,让我给你一个很快的认识。
在这一点上,我们的无域iframe能够访问bing的空白iframe,但访问机制是非常重要的。我们不能直接访问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
那么我们该怎么办呢?很容易,在窗口中使用iframe的名字打开一个javascript url。如果bing的内部iframe名称是“INNER_IFRAME”,以下代码将会很好地工作:
window.open("javascript:alert(document.cookie)", "INNER_IFRAME"); // SOP BYPASSED!
但是很尴尬的一个问题,Bing中iframe没有命名!不过不要灰心,我们可以请求bing团队对这些iframe进行命名。或者我们可以继续挖掘绕过方法~
设置iframe名字
我们不能设置目前我们没有拥有的iframe名称,除非它与我们在一个域中。我们要在bing中产生一个空白的iframe。外部的iframe处于不同的域中,但是标签本身(元素,对象)是在我们的域中。所以,我可以设置任何名字:
<iframe name="ANY_NAME" src="http://bing.com">
<iframe src="about:blank"></iframe>
</iframe>
但是内部的iframe是通过bing渲染的,所以即使他是空白页面,他的域照样是bing.com。惟一更改名称方法是先将iframe的位置设置到我们可以访问到的地方,然后才能更改它的名称。现在,如果我们改变about:blank的位置,所以我们需要先成为bing.com,,然后我们才能访问到无域的空白页面。这就像从脚下进行拍摄一样困难。
记住:我们的目标是从一个无域的页面到一个域中的页面。如果我们将域设置为要匹配的域,比如上述的bing,那么这个攻击毫无意义。所以我们将要做的是:设置位置,更改iframe名称,然后以这样的方式恢复位置,以保持原始域。听起来很复杂?下面是这个方法的总结:
1.iframe的位置设置为about:blank,将其域更改为我们控制的域:crack.com.ar
2.更改iframe名称
3.将其位置重新设置为about:blank,但这次使用一个元刷新,使得它的域名等于它的创建者:bing.com。
上述就是攻击的方法,他的域已经恢复到了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页面的iframe,因为我们总是可以像上面那样做。换句话说,bing的内部iframe是不是about:blank并不重要,因为我们最后可以通过原始域对空白页面进行设置。
成功的大门为我们敞开,我们最后可以使用在iframe中的”数据-元-数据”执行一条命令。
测试这一漏洞的POC地址:http://unsafe.cracking.com.ar/demos/edgedatametadata/bing.html
视频地址:https://youtu.be/E_6OFcTi5kQ
关于PoC,一个重要事项:在上面的示例中,我们使用http(不安全)连接,因为在https(安全)中,数据的元刷新会被阻止,所以它不会重定向到最终的数据uri。Edge错误地认为重定向是不安全的。然而,这可以通过使用document.write而不是第一个data:uri来轻松绕过。所以代替”数据-元-数据”应该是document.write-元-数据。
我们没有在上述的PoC中使用它,因为在进行演示交互时(让你按下按钮来运行它)Edge检测https用了1/3的时间。所以,我选择在http和https自动使用以及可靠的PoC。但是无论如何,如下所示,它并不重要:我们的不安全(http)无域空白页面能够访问安全页面,所以让我们建立一个真实的例子。
攻击的真实案例:盗取Charles的cookie
是时候去进行真正的攻击了。Charles是一个比较具有安全意识的用户,他从来不在同一个页面打开相关链接,比如在twitter,gmail以及它的个人文档中。
让我们来看一看,他正在通过选项新建一个标签页打开链接。
他的心情很好,直到他用Twitter的账号打开了另一个标签,并为阿尔弗雷德·华莱士(Alfred Wallace)提供了关于谁先推送的消息。
几分钟后,华莱士的回应就包括了支持他的声明的证据。但是请记住,Charles不信任任何人,所以他复制了链接,以将其粘贴到一个新的窗口中,远离他拥有个人数据(gmail,twitter)的窗口。
没有任何一处地方是不可以出错的,像这个世界上的大多数网站一样,twitter同样有几个iframe。事实上,他有两个命名为about:blank的iframe。所以这次的攻击应该比bing简单一些。但是在回到我们的故事之前,我们使用调试工具找到一个合适的iframe攻击点。我在这里打开另外一个新的窗口,与Charles的会无关。
漂亮,dm-post-iframe是一个非常好的选择,所以我们有了盗取Charlie账户的所有条件。
Charlers打开了一个新的标签页,并加载了华莱士给他的网址。他不知道的是,即使在不一样的标签页,也可以相互通信。那么,如果我们在无域iframe中执行下面的代码,会发生什么?
window.open("javascript:alert(document.cookie)", "dm-post-iframe");
你是完全正确的,我们有Charlers的cookies~
警告:以下的概念证明将请勿做任何攻击。
漏洞执行Poc:http://unsafe.cracking.com.ar/demos/edgedatametadata/cookiesfromcharlie.html
请记住,我们真的不需要在窗口内部打开。上面的例子试图说明一个偏执的情景,但通常情况下更容易,因为人们点击链接,而不用完成Charles所做的所有工作来防止攻击。
作为Charles发送推文
为了建立一个更好的PoC。我们将以他的名字发推文,甚至尝试抓取他的密码,而不是阅读他的cookies。请记住,大多数用户(如查理)使用自动填写密码的密码管理员。
Edge密码管理器没有什么不同,所以如果Charles保存了他的密码,我们会得到它。这不是很难,只是强迫他注销,然后登录页面将被自动加载,所有的数据(用户名和密码)会被重放。事实上,在这种情况下,除非用户进行交互,否则窗体是隐藏的,但是Edge正在填充它,所以我们甚至可以设置窗体不可见。
在运行PoC之前,请考虑这是您的帐户,而不是Charles。没有任何东西被发送到网络,但如果你身后有人,他会在一个常规警报对话框中看到您的密码。
原文发布时间为:2017年5月5日
本文作者:xnianq
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。