在现代的Web开发中,将来自不同来源的内容集成到一个页面上是很常见的需求。例如,Twitter小部件可以显示关于产品的最新推文,Facebook评论可以讨论文章,或者通过IFRAME元素集成网页。这些集成体验虽然提高了用户体验,但同时也增加了网站安全风险。
本文将介绍HTML5的Sandbox特性,这是一种新的解决方案,可以帮助提高网站安全性,防止IFRAME中的嵌入内容对网站造成安全威胁。
使用IFRAME嵌入内容就像是在Facebook上公开宣布一个派对。以为知道邀请了谁,但实际上并不知道谁转发了邀请,也不知道谁会出席。
同样,对于框架内容,知道引用了什么,但并不知道这个站点将来会如何演变。内容或功能(或两者)可以随时更改,而并不知道,也未经同意。
浏览器处理使用IFRAME的页面就像处理任何其他网页一样。可以使用表单来获取用户输入,可以执行脚本,页面可以在浏览器窗口内导航,可以执行浏览器插件。就像派对上的不速之客一样,无法控制托管内容会做什么。
默认情况下,有一种机制可以防止某些类型的攻击:跨域策略。
如果托管内容来自另一个域,跨域策略就会发挥作用,它禁止“外来”内容访问父文档对象模型。
因此,嵌入的页面无法读取例如cookie或托管域的浏览器本地存储。但仍然存在风险。
托管内容仍然可以在顶级重新导航。通过显示用户期望的内容,站点可能会尝试从用户那里钓鱼机密信息。或者,通过使用类似风格的表单,尝试以恶意方式捕获用户信息。
因此,即使有跨域策略,仍然存在很大的安全风险。
从同一域重新托管内容的情况更糟。
当内容来自同一域时,没有默认的安全限制。嵌入的内容可以访问完整的加载的浏览器DOM,并操纵一切。
这里的风险主要来自于在IFRAME中重新托管的用户生成的内容。
这些有效的安全问题长期以来没有得到标准机构的妥善解决。没有明确的W3C标准,有必要以某种方式保护主机免受框架内容的侵害。例如,微软在Internet Explorer 8中提供了IFRAME安全的专有实现。其他人也采纳了这一点,并将其作为他们浏览器的基线。但自IE8以来,标准已经大大成熟。
包括Chrome、Firefox和IE10平台预览在内的现代浏览器都基于W3C IFrame Sandbox属性。
让开始应用沙箱。只需将沙箱作为空属性添加到IFRAME元素:
<iframe sandbox src="http://somewebsite.com/default.html"></iframe>
就是这样!
现在,沙箱化的IFRAME内容在浏览器中重新托管,具有以下限制:
这意味着即使来自同一域的内容也被视为跨域策略,每个IFRAME内容都将被视为唯一来源。
嵌入的内容只允许显示信息。IFRAME内不允许执行任何可能危及托管网站或利用用户信任的操作。
知道IFRAME是一个敞开的大门。知道沙箱属性锁定了托管内容的安全性。
决定是明确的:只使用带有沙箱属性的IFRAME元素!
可以用一个简单的JavaScript检查来确认浏览器是否支持IFRAME沙箱属性:
if ("sandbox" in document.createElement("iframe")) {
// 渲染iframe元素...
} else {
// 通过其他方式嵌入内容,
// 因为浏览器不支持沙箱
}
如果支持,就使用沙箱属性。如果不支持,尝试通过其他方式嵌入内容,或者鼓励用户升级到现代浏览器。
在某些情况下,可能需要对限制进行一定程度的自定义,这是绝对可能的。
几个属性值放宽了标准沙箱策略:
可以在沙箱上组合几个属性值。例如,如果想启用表单回发、顶级导航和JavaScript,只需指定:
<iframe sandbox="allow-forms allow-top-navigation allow-scripts" src="xyz.html"></iframe>
还应该知道,沙箱在层次结构情况下使用时表现正确,使用具有不同沙箱属性值的几个嵌套IFRAME。顶级沙箱总是支配层次结构。
可以在中尝试HTML沙箱。可以从Github下载这个演示的副本。要启用表单回发演示,只需在WebMatrix中打开项目文件夹,然后从那里启动项目。