javascript 沙箱实现
从一个经典的跨域脚本应用说起:
JSONP 是一个流行的跨域获取数据的方案,它原理是向文档动态插入一个 script 标签,向远程服务器发起一个脚本请求,然后远程服务器返回一个定的回调函数并传入 JSON 数据,这样完成跨域数据交换。
如页面预先定义一个全局函数:
1 |
window.jsonp534533 = function (json) { |
2 |
//... |
3 |
} |
向服务器发起 script 请求 JSONP
http://api.douban.com/jsonp?key=3435&type=music&callback=jsonp534533
服务器返回 js 文件
1 |
jsonp534533({ |
2 |
"code" : 0 |
3 |
"data" : [...] |
4 |
}) |
JSONP 虽然很方便实现前端跨域,但是其弊端也是显而易见的:无法保证安全性。
由于是 script 直接执行,假若提供 JSONP 服务器返回了恶意代码 (如被黑客入侵),这样将会十分危险。恶意代码可以向页面插入广告或者直接重定向第三方站点、甚至可以窃取 cookie 用 N 种方式发送到第三方服务器,这些都直接威胁站点安全。
有没有一种纯前端的方案可以安全的加载 JSONP 呢?我们可以提供沙箱环境来加载外部脚本。
javascript 沙箱
一个安全的 JSONP 脚本它只给回调函数传入数据而不应该读写 document,更严格一点是不能进行任何的 DOM 与 BOM 操作。基于此,我们可以利用空白 iframe 新建一个脚本执行环境,然后限制 iframe.contentWindow 的 DOM 与 BOM 方法,让这个环境中运行的脚本无法读写主页面,也无法发起任何通讯请求,这样理论上实现了一个 javascript 沙箱环境。
由于浏览器 DOM 与 BOM 实现机制不同,我们可以结合以下两种方式编码。
一、覆盖原生的方法与属性
- this.__proto__ = {} (现代浏览器)
- 设置全局同名函数(IE为主)
- 向文档插入一个同名 name 属性的 iframe (针对opera)
二、使用 HTML5 iframe “sandbox” 属性
HTML5 iframe “sandbox” 属性可以限制 iframe 内容的权限。这个属性目前只有 chrome 、 safari 、IE10 支持,而且这个属性可选项太少,虽然能够限制 ajax 请求,但无法阻止传统的跨域请求,如 new Image 或者 script 方式。
javascript 沙箱应用场景畅想
除了安全加载 JSONP 之外,沙箱机制还可以为社交平台实现安全 javascript API 提供可能:
由于安全问题,社交平台第三方 APP 大多以 iframe 形式载入,但是由于 iframe 本身的问题,这样体验远远不能达到“原生”应用的高度。针对此我们可以给 APP 开发者设计一个应用 API,让其只能在沙箱环境中操作 APP 自身的 DOM 与有限的公用 API,而没有访问全局对象的能力,从而实现体验与安全完美合一。
scriptSandbox 项目
scriptSandbox 是上述想法而创建了一个开源项目,正如本文所述,它实现了沙箱环境用来隔离 JSONP 可能出现的危险操作。scriptSandbox 项目主页:
http://code.google.com/p/script-sandbox/
特别说明:下载包中含有测试脚本 test.js, 它除了传递 JSONP 外,还模拟了 “危险” DOM 操作,你可以在不同浏览器中测试沙箱隔离能力。欢迎您在 test.js 写“危险”代码对沙箱进行攻击,若实现下面要求均算成功成功:
- 获取页面 document 访问能力
- 获取与服务器通讯能力
- 弹出对话框
欢迎您给我提交漏洞报告 1987.tangbin(a)gmail.com
参考文档:
http://www.infoq.com/cn/news/2010/01/HTML-5-Sandbox-IFrame
http://w3help.org/zh-cn/causes/BX9045
原文:http://www.planeart.cn/?p=1732
本文出自 传播、沟通、分享,转载时请注明出处及相应链接。
本文永久链接: https://www.nickdd.cn/?p=1853