本文讲的是
小心阅读模式下的猫腻——看看我如何在Edge的阅读模式下绕过SOP,
Microsoft Edge全新的浏览器让人眼前一亮,而阅读模式可以说是其中的亮点之一。不过今天我们并不是要评价它的这个功能,而是要对运行在Edge浏览器 阅读模式下的各种伪协议运行机制进行一个详细的解剖。
要打开阅读模式,可以进入Edge浏览器,点击像一本书一样的图标,即可进入阅读模式:
使用阅读模式,阅读效果会更好一些:
但是,阅读模式页面下的真实地址是什么呢?打开开发者工具(F12)并在控制台中输入 location.href 。从下图可以很明显的看到,此时,Edge浏览器 在 URL 前面添加了 read: 伪协议:
以下我所描述的这些漏洞适用于所有的Edge版本,但本文所提到的PoC则是专门针对Edge浏览器15.0以后的版本而构建的。 如果有人想要15.0以前的旧版本上执行这个POC的话,必须进行相应的修改,以确保在阅读模式下呈现出来。
实际上阅读模式下的网站是一种内部资源
阅读模式下的网页并不是常规阅读模式下的那个网站,如果你按Ctrl+U快捷键来看看源代码的话,你会惊奇的发现,你根本找不到原始页面的任何踪迹,实际上阅读模式下的网站是一个托管在文件系统中的内部资源:
C:WindowsSystemAppsMicrosoft.MicrosoftEdge_8wekyb3d8bbweAssetsReadingView
Edge浏览器会解析原始网页的内容,删除iframe / scripts及其他html标签,最后将其呈现在内部阅读视图html中托管的iframe中。不过所有这些操作都发生在后台,用户根本就一无所知,当用户切换到阅读模式时,他们会以为这些内容的浏览地址还是停留在刚刚的网站上,因为他们并没有对网址进行过改动。
但如果在Edge浏览器的原始URL之前设置“read:”协议,然后再在阅读模式下呈现网页的话,我还可以利用脚本来执行吗? 我可以自动在阅读模式下随意加载网址吗?
随意强制一个网站进入阅读模式
我们来看看是否可以通过前置read:协议来强制把任意的URL从正常阅读模式切换为阅读模式:
location.href = "read:http://www.cracking.com.ar"; // prepending read: does the trick
虽然这种做法的效果非常好,但仍有一些进程引起了我的注意,比如虽然地址栏中的URL是crack.com.ar,但切换到阅读模式后,URL却是brokenbrowser.com。这是怎么发生的呢?
于是我试着检测了一下crack.com.ar,如下图所示,我看到看到 location.replace 将其跳转到了brokenbrowser.com,但Edge浏览器却并没有更新地址栏!
所以我总结的第一个漏洞便是:当脚本或 http 重定向发生时,Edge并不会更新地址栏:
寻找一个重定向
以上的操作意味着我们可以利用重定向这个机会把阅读模式下的网站伪装成任意网站,甚至可以对所有重定向到我们控制之下的网站进行伪装,反正用户在阅读模式下的视觉呈现效果不会发生什么变化。 例如,如果我可以把google.com重定向为一个恶意的页面,但用户还会认为他们的阅读内容来自谷歌,实际上它是来自evil.com。
另外,考虑到所有搜索结果都是重定向至目标的形式,所以伪装成google进行重定向并不是不会很难。 例如,google从crack.com.ar索引了一个 “crack-01.html” 页面,如果能找到重定向到“crack-01.html”页面的原始链接的话,那操作就轻而易举了,因为这是我自己的服务器,所以可以任意修改它。不信,你可以打开Chrome,找到一个重定向到crack.com.ar服务器的链接。
不过请注意:由于你的目标是找到一个重定向到crack.com.ar的google URL,所以该网站正好处于我的控制之中:
在阅读模式下重定向
现在,我已经有一个重定向到crack.com.ar的google.com.ar的 URL了,下面,我要做的就是在crack.com.ar中的网页中写一些文字,例如“该网站是伪装的Google网站”等类似的提醒语句,这样我就可以很容易地确定阅读模式下看到的内容的真正网址了。 以下是前置了read: 伪协议的google重定向,在Edge浏览器中打开时的界面如下所示:
read:https://www.google.com.ar/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiRx_eksaTTAhURl5AKHcrxCuoQFgggMAA&url=http%3A%2F%2Fwww.cracking.com.ar%2Fcracking-01.html&usg=AFQjCNGa3PACMDlI6RdBOnoEfySVh1C2ZQ
从上图可以看出,虽然伪装的网页非常成功,但别忘了,我们是在阅读模式下完成的这些。这也就意味着我还没有完全控制页面的阅读形式的呈现外观。因为在呈现页面之前,Edge浏览器还会删除大量的HTML内容。例如,iframe 和 script 都会被删除,并且JavaScript链接的进程也被停止了。那么,我该如何自定义这个页面并删掉后面的淡黄色背景呢?又怎么在其中运行脚本呢?
在阅读模式下运行脚本
处于阅读模式下,Edge浏览器会尽力把所有呈现出的内容都保持成静态的,即不允许任何脚本,连iframe等也会被删除。也就是说,阅读模式下的内容最终要像一本书那样静静的呈现出来,而不是向网页那样动态变化。下面我就将试着处理保持这种静态阅读模式的一些障碍。
我先手动测试了几个html标签,比如iframe / script / meta,但是它们都会被删除。然后,我尝试了一下object/html标签,令我惊讶的是,这两个标签竟可以正常运行,看来事情比我想象的要更容易一些,object/html 标签类似 iframe :,它们都是可以运行 script 的 html 容器 。
所以我总结的第二个漏洞便是:当在阅读模式下呈现页面时, Edge浏览器并不会删除object/html标签。
所以,如果我在crack.com.ar中的页面中添加一个object/html 标签,然后触发一个提示的话,那么一切看起来就顺其自然了:
<!-- prompt.html does a window.prompt with the hard coded "google.com needs..." message --><object data="http://www.cracking.com.ar/prompt.html"></object>
现在,Edge浏览器会认为所阅读的网页源自google.com.ar,事实上,它是源自crack.com.ar,因为object/html是源自crack.com.ar。但问题是,虽然我可以触发提示或警报提示,但我还是无法访问真正的网站。
假设我要将网站的背景颜色便为白色或使用其它更有说服力的攻击手段,就需要绕过SOP或设置网站顶部的 URL,而不更改地址栏。下面,就让我来尝试SOP 绕过吧!
浏览器有一个很重要的概念——同源策略(Same-Origin Policy,SOP)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。
简单的来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。
如果Web世界没有同源策略,当你登录嘶吼的官网并打开另一个站点时,这个站点上的JavaScript可以跨域读取你的嘶吼账号数据,这样整个Web世界就无隐私可言了。
寻求父页面的相匹配
如何让顶部的域来呈现任意 html 代码,以实现对真实网页的访问?也许data uri 是个不错的选择。与在 cracking.com.ar 上托管的内容不同,在 data uri中呈现html,如下所示:
<!-- object rendering a data uri --><object data="data:,<script>alert(top.location)</script>"></object><!-- ACCESS DENIED data uris have their own unique origin -->
不过事情没那么简单,因为Edge浏览器不允许我利用data uri访问任何其他文档。所有浏览器都把data uris当作不同于其创建者的独立源进行处理,但在Edge浏览器上,这个限制却很容易被绕过。页面加载后,仅仅使用一个self-document.write就足以匹配父页面的域了。
所以我总结的第三个漏洞便是:在data: uris中,可以通过document.write设置源,使其与其父页面相匹配:
<object data="data:,<script>window.onload = function(){ // Executing a document.write in a data uri after the onload // changes the location of the object to its parent URL. document.write('<script>alert(top.location.href)</script>'); document.close();}</script>"></object><!-- Now we have the same location as our top -->
现在我已经成功绕过SOP,让我们来看看能否 访问真正 的Google 的顶级域名?现在,我完全可以在不用改变任何设置的情况下,访问阅读模式状态下的内部 html 代码了,用 top.document.write 即可把淡黄色的背景改为白色的了。
<object data="data:,<script>window.onload = function(){ document.write( '<script>'+ 'top.document.write('Trust me, we are on Google =)');'+ 'top.document.close()'+ '</script>'); document.close();}</script>"></object>
本文的技术手段如果要总结成一句话,那就是利用Edge浏览器的阅读模式(read: 伪协议)实现地址栏欺骗,然后进一步利用 <object data:> 实现完整的页面伪造。
原文发布时间为:2017年4月21日
本文作者:xiaohui
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。