<portal>是一个相当新的HTML元素,目前仅#enable-portals标志后面的Chrome Canary支持。正如这篇文章所述,其主要目标是通过在类似<iframe>的元素中预先呈现内容,然后将其“提升”(激活)为一个新的样式,从而实现无缝过渡到Toplevel(顶级窗口)组件的Frame组件。Portal作为网关服务于因特网的一种WEB站点。Portal是链路、内容和为用户可能找到的感兴趣的信息(如新闻、天气、娱乐、商业站点、聊天室等)的指南服务的集合。Yahoo、Excite、MSN.com和Netscape NetCenter都是Portal。portal是一种web应用,通常用来提供个性化、单次登录、聚集各个信息源的内容,并作为信息系统表现层的宿主,聚集是指将来自各个信息源的内容集成到一个web页面里的活动。
本文,我们将分析包括绕过同源策略(same-origin policy)以及Chrome中的本地文件泄露。另外,我还将在GitHub存储库中发布本文中显示的所有示例。
什么是<portal>?
首先,<portal>是什么,为什么我们需要它?总的来说,<portal>是一个新的HTML元素,可以嵌入内容。但是,它的行为与<iframe>明显不同。主要区别在于:
1. 你无法从嵌入器访问<portal>中嵌入的站点的DOM树,这意味着没有frames[0],没有contentWindow/contentDocument,也没有命名窗口访问。这样就可以在不同的事件循环中运行<portal>中嵌入的内容,实际上就是Chrome Canary在新进程中运行嵌入的内容。
2. 在嵌入器和嵌入内容之间进行通信的唯一方法是使用postMessage调用进行异步通信;
3. 嵌入的内容实际上就像是顶层浏览上下文一样工作。这意味着即使即使它是嵌入式页面,在门户top === window中,它也等于true。找出页面是否在门户网站中呈现的唯一方法是检查全局变量portalHost是否等于null或。
4. 可以通过调用<portal>.activate()方法将portal元素提升到顶层上下文。不过这些内容不会重新渲染,而只是从门户“跳转”到顶层框架。看看下面的动图,执行portal.activate()之后,它的内容不会重新呈现,而是立即成为顶层框架,这是<portal>提供的独特功能。
以下是使用门户的HTML示例:
<!doctype html><meta charset=utf-8>
<portal src= id=portal></portal>
<button onclick=portal.activate()>portal.activate()</button>
<portal>的安全风险
熟悉<portal>是什么以及它如何工作之后,我们现在就开始提出有关潜在安全问题的问题。第一个是关于URI的,它是嵌入在<portal>中的内容,其行为类似于顶级框架。并且允许用户在地址栏中输入各种非HTTP方案,包括典型的方案,例如http: 或https :,还包括file: ,data: 或javascript:。所以,我想知道我们是否可以对门户网站做同样的事情?
<portal>表现得像顶级框架的另一个直接后果是点击劫持(ClickJacking)问题。点击劫持是一种典型的Web安全问题,是一种欺骗手段。大概有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的iframe页面;二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义;浏览器不会将X-Frame-Options用于顶部框架。这是否意味着<portal>为Clickjacking创建了一种新的简便攻击方法呢?
在下面的部分中,我将回答这些问题以及在研究过程中出现的其他一些问题。
风险1:接受不安全的URI方案
当用户在地址栏中手动输入地址时,通常允许她访问多种URI方案,比如:http:,https:,file:,chrome:或data:。尽管可以手动访问这些方案,但不允许网站在顶层框架中将用户重定向到http或https之外的其他方案。例如,如果某个页面试图将用户重定向到file:///etc/passwd,Chrome将出现异常加载警告:不允许加载本地资源:file:///etc/passwd。
进行第一次测试时,结果发现相同的限制并不适用于<portal>,并且我可以打开所需的任何页面,包括file:甚至chrome: schemes。
此视频显示了<iframe>和<portal>之间的对比情况,你可以看到file:甚至chrome: schemes都显示在<portal>中。
注意:你可以在以上视频中看到被称为Portal-playground的页面,你可以在该GitHub存储库中找到它,如果你愿意还可以在其中加入一些门户。很明显,浏览器不允许打开任意URI方案,但上面的示例并不构成直接的安全漏洞。但是,当你意识到还可以将javascript: scheme分配给URL时(就像在bookmarklet中一样),你立马就能发现其中的漏洞!Chrome Canary中存在一个安全漏洞,可以在其他来源的上下文中执行任意javascript,这个想法如下。
portal.src =
// and after a while...
portal.src = javascript:... // this executes in
注:Bookmarklet,合成词(Boolmark Applet),基于浏览器收藏夹的小书签应用。通常一段Javascript代码就是应用的全部。可以在一定程度上替代浏览器扩展。
该视频展示了我如何能够从和file:///etc/passwd窃取数据,你可以点此链接,请查看漏洞利用代码以确切了解其工作方式。
该漏洞已于2019年5月13日报告给Google,并已确认于2019年5月26日修复,详情请点此查看。
简单来说,缓解方法就是添加一个检查,以确保门户的源位于HTTP家族中。
能够在门户网站中打开任意URI然后再激活它的另一个有趣的副作用是能够打开数据,这些数据位于顶层框架中的URL。不过目前,Chrome和Firefox都具有禁止打开数据的保护功能,即你无法打开顶层框架中的URL。如果尝试这样做,则会出现这样的异常情况:不允许将顶层框架导航到数据URL: data:,text。
有趣的是,当你打开数据,即门户中的URI,然后将其激活时,你就会在顶层框架中看到数据URL!目前,该问题在Chrome中也已被修复。所以你无法在门户网站中打开非HTTP URL,也无法导航到数据URL。
风险2:点击劫持
点击劫持可能是与<portal>相关的最严重的风险,它主要是通过X-Frame-Options响应标头在iframe中被击败的。对于门户网站,此修复并非那么容易。因为嵌入的内容可以像顶层框架那样工作,所以X-Frame-Options不会被考虑。
Chrome当前采用的解决方案是使嵌入的内容不接收鼠标和触摸事件,因此,即使你单击<portal>内容,也不会发生任何事情。虽然规范中没有明确说明,但这似乎是理智的方法。
键盘事件也应该被阻止,但在测试时就不要这样做了。这样,你就可以使门户网站内的按钮成为焦点,然后在用户按下ENTER键时单击该按钮,具体过程如该视频所示:
首先,我尝试了几次单击按钮,但无济于事。然后,使用键盘进行聚焦,然后按Enter,最后单击按钮。
我注意到门户内容可以通过两种方式获得关注:
首先:如果设置<portal contenteditable>,则在单击TAB按钮后它会进行聚焦。
第二:如果嵌入的内容包含具有id的元素,则只需将其指向URL: <portal src=page.html#id>,然后它将被聚焦。
目前,此安全问题也已报告给Google,代码为bug#,从Chrome 78起至今仍未修复。
我认为,<portal>元素的主要工作是显示页面的内容,而不是以任何方式与之交互,因此,我认为应该明确规定<portal>中嵌入的内容不应接收任何鼠标,触摸或按键事件。
风险3:其他框架风险
点击劫持并不是嵌入内容的唯一风险,Frederik Braun和Mario Heiderich在一篇名为“X-Frame-Options:All About Clickjacking?”的论文中清楚地解释了其他风险。在本部分中,我将向你介绍目前无法防御的门户网站可能发生的一种攻击。假设你访问某个网站并看到如下所示的验证码:
它可能看起来有点可疑,但是可以通过将代码拆分到几个验证码中来进行具体分析。那么实际的代码是什么?进入,就可以看到Shodan的API密钥。
Shodan 是一个搜索引擎,但它与 Google 这种搜索网址的搜索引擎不同,Shodan 是用来搜索网络空间中在线设备的,你可以通过Shodan搜索指定的设备,或者搜索特定类型的设备,其中Shodan上最受欢迎的搜索内容是:webcam,linksys,cisco,netgear,SCADA等等。那可以采取可以采取哪些措施来防止在恶意网站上显示作为验证码的密钥?可以肯定的是X框架选项不适用于门户网站,唯一的方法是检查portalHost全局变量,但是你不能期望世界上的所有网站都会访问到它。
为此,我们总结了两个很好的解决方案:
1. 与<iframe>相似,为<portal>应用X-Frame-Options。虽然该方案有自己的有点,但缺点是<portal>会创建一个顶层框架,该框架与被X-Frame-Options阻止是不一致的。
2. 使<portal>成为启用功能,如果网站的开发人员希望将页面嵌入门户中,则用户将必须明确设置标题,例如“Sec-Allow-In-Portal: 1”,该方案还将解决本文中描述的其他安全问题。从Chrome 78开始,此问题尚未呗修复。
风险4:XSSearch/XSLeaks
2018年年底,有研究人员详在谷歌的Monorail问题跟踪平台()上 ,发现了跨站搜索攻击(XS-Search attack),从一些谷歌未公开的漏洞报告中,获取源代码和涉及函数所在行数等敏感的漏洞报告信息。跨站搜索攻击(XS-Search Attack,XS-Timing Attack on search service):类似边信道攻击,通过向目标站点发送搜索请求,结合特定搜索功能,根据响应时间差异(XS-Timing)来判断目标服务端隐私信息的准确性,间接绕过”同源策略“影响,是一种新型的Web攻击方式。在可搜索信息量较大,或目标服务端搜索功能多样化的场景下,是一种有效的信息获取手段。
XSSearch(跨站点搜索)和XSLeaks(跨站点泄漏)是最近几个月浏览器安全中两个新的热门话题。这些攻击主要是通过滥用浏览器侧信道来推断另一个站点的行为而进行的。你可以在XSLeaks GitHub存储库中了解有关它的更多信息。我将展示两个示例,其中<portal>使事情变得简单:定时攻击和检测XSS审核程序。
使用<portal>进行定时攻击非常容易,因为它会在嵌入式内容加载后触发onload事件。因此,攻击就像在加载门户网站之前花时间然后在onload事件中减去它一样简单。不尊重X-Frame-Options会使攻击更加有价值。详细代码,请点此处查看。
检测XSS审核程序也很容易,唯一需要做的事情就是计算触发了onload事件的次数。如果审核程序配置以阻止模式工作,那么将触发两次onload事件。否则,该事件仅触发一次。为此,我准备了一个简单的代码来检查它,你可以在下面的操作中看到它:
从Chrome 78开始,由于XSS Auditor边信道已从Chrome中删除,因此它不再起作用。
风险5:端口扫描
检查onload事件触发次数的能力使我想知道是否还可以进行端口扫描。令人惊讶的是-是的!你可以确定是否为各种网络服务(不仅是Web服务器)打开了端口。
关键只是为了计算onload事件被触发的次数,当我发现这取决于显示错误页面的确切原因时,我感到有些惊讶。具体过程如下所示:
1.当Chrome显示ERR_CONNECTION_REFUSED错误时,onload事件触发了5次;
2.当Chrome显示ERR_INVALID_HTTP_RESPONSE或ERR_EMPTY_RESPONSE时,onload事件触发了4次。
实际上,onload可能触发了不同的次数,但基本上,你可以基于onload事件的偶数或奇数来判断错误的原因。
下面显示了服务器上端口扫描的示例,其中包含:
1. 端口3306和80已打开;
2. 端口3307已关闭;
3. 端口3308已过滤。
以下就是端口扫描功能的输出内容:
你可以在以下链接中找到端口扫描程序的来源: 。
从Chrome 78开始,该攻击始终有效。
风险6:逃避CSP(内容安全策略)
也许你也可以滥用门户来逃避Content-Security-Policy。在CSP可以实现的众多功能中,你还可以使用frame-src或child-src指令来限制可以在你的域的iframe中放置哪些域。如果你认为CSP对门户网站没有任何影响,那就错了。在<portal>中显示内容时,似乎同时考虑了frame-src和child-src。这基本上意味着以下代码将导致错误:
<meta http-equiv=Content-Security-Policy content="frame-src none">
<portal src=""></portal>
错误显示如下:
尽管有错误消息,但它与扩展无关。否则,门户网站很容易被用来绕过CSP并泄露数据。
风险7:SameSite Cookie
Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪。SameSite是cookie的标志,可通过确保带有此标志的cookie只能发送到同一域来防御CSRF攻击以及其他风险。如果SameSite将执行其工作,则不应将其发送到<portal src=;</portal>发起的请求中。
下面我会建立一个简单的示例进行检查,我的页面设置了三个Cookie,分别是:
1. SAMESITE_STRICT,带有标志SameSite=Strict,
2. SAMESITE_LAX,带有标志SameSite=Lax,
3. NO_SAMESITE,没有任何SameSite属性。
然后,我同时检查<iframe>和<portal>来查看是否发送了这些cookie,如你在下图中所见,这三个cookie都被发送到门户,而只有NO_SAMESITE被发送到iframe。
从Chrome 78开始,行为略有改变:现在SAMESITE_STRICT Cookie尚未发送到门户。虽然NO_SAMESITE cookie仍用于门户网站,但未发送到iframe。
风险8:下载文件
在Chrome浏览器中,当你访问下载文件的页面时,该文件将立即下载:你可以在窗口底部显示的栏中看到它。如果某个网页试图恶意并立即下载多个文件,则Chrome会要求获得明确的许可,如下图所示:
当你在<portal>中打开一个下载文件的页面时,该文件也会立即被下载。但是,防止下载多个文件的保护不再起作用。你可以根据需要多次刷新门户,Chrome可以无限次地下载文件。
具体过程,请点此视频观看。详细内容,请点此。从Chrome 78开始,该攻击一直有效。
风险9:悬挂式标记(Dangling Markup)
悬挂式标记是一种非JavaScript渗透攻击,该攻击的思路是,如果你无法注入JS代码,则还可以使用非终止标记来渗出数据。最常见的滥用悬挂式标记如下所示:
<img src=?
<input name=csrftoken value=secret type=hidden>
然后,开始和结束单引号之间的所有内容都发送到外部服务器。一段时间以来,Chrome内置了针对这种攻击的保护措施。因此,上面的示例不适用于当前版本的Chrome。
但是由于某些原因,<portal>不能使用相同的保护。这意味着使用下面显示的代码,你仍然可以提取数据:
<portal src=?
<input name=csrftoken value=secret type=hidden>
你可以在以下链接中使用示例进行操作:。从Chrome 78开始,该攻击一直有效。
总结
在本文中,我描述了新的<portal>元素,当前仅在Chrome Canary中受支持。受当前该规范缺乏任何安全考虑的事实的启发,我介绍了使用门户可能引起的各种安全问题。
参考来源: