日期:2014-05-16  浏览次数:20735 次

征服 Ajax 应用程序的安全威胁

Ajax 构建于动态 HTML(DHTML)技术之上,其中包括如下这些最常见的技术:

  • JavaScript :JavaScript 是一种脚本语言,在客户端 Web 应用程序中经常使用。
  • 文档对象模型(Document Object Model,DOM) :DOM 是一种用于表示 HTML 或 XML 文档的标准对象模型。如今,大多数浏览器都支持 DOM 并允许 JavaScript 代码动态地读取和修改 HTML 内容。
  • 层叠样式表(Cascading Style Sheets,CSS) :CSS 是一种用于说明 HTML 文档表示的样式表语言。JavaScript 能够在运行的时候对样式表进行修改,这样便可以动态地更新 Web 页面的表示。

在 Ajax 中,客户端 JavaScript 通过动态地修改 DOM 树和样式表来更新 Web 页面。此外,异步通信(可以通过下面介绍的技术实现)允许动态地更新数据,而无需重新加载整个 Web 页面:

  • XMLHttpRequest XMLHttpRequest 是一个 API,它允许客户端的 JavaScript 与远程服务器建立 HTTP 连接和交换数据,比如说纯文本、XML 和 JSON(JavaScript Serialized Object Notation)。
  • JSON :JSON 由 RFC 4627 提出,是一种轻量的、基于文本的、独立于语言的数据交换格式。它以 ECMAScript 语言的一个子集为基础(这使之成为 JavaScript 语言的一个部分),并且定义了一小套格式规则用以创建结构数据的可移植表示。

注意,Ajax 应用程序中还有一些其他常用的格式可以替代 JSON,比如说 XML 和无格式的纯文本。此处我们选择讨论 JSON,其原因在于它具有一些隐藏的安全问题,稍后我们将在文章中对其进行研究。

建议对 Ajax 还不熟悉的读者先阅读 参考资料 中的文章。

?

理解同源策略

当来自多个始发源的内容以某种方式被集成到一个单一的应用程序中时,一些内容相互之间可能具有不同的信任级别,或者它们可能根本没有必要相互信任。这样自然而然会产生某种需求,即把来自不同始发者的内容分离开来,把它们之间的冲突减至最少。

?

同源策略是当前浏览器的保护机制的一部分,该机制将来自不同域(假设域代表的是始发者)的 Web 应用程序分离开来。也就是说,如果多个窗口或框架中的一些应用程序是从不同的服务器下载的,那么它们无法相互访问数据和脚本。注意,同源策略只能应用于 HTML 文档。通过 <script src="..." > 标记导入 HTML 文档的 JavaScript 文件被认为是该 HTML 文档的同源的一部分。该策略在所有主要浏览器实现中都有执行。

?

XMLHttpRequest 的上下文中,同源策略的目的是控制应用程序与远程服务器的交互。然而,同源策略对 Web 2.0 应用程序的影响力比较有限,这有如下几个原因:

?

  • 可以通过许多方法绕过同源策略 :稍后我将在文章中演示其中的一些方法。
  • Web 2.0 应用程序的一个重要特性就是用户对内容的贡献 :也就是说,通常内容并不是由受信任的服务提供的,而更多的是由异步用户通过 blog、wiki 等媒介提供的。因此,即便是单个服务器中的内容实际上也能够来自多个来源。
  • 浏览器强制同源策略将服务器的域名作为串字面值进行检查 :例 如,http://www.abc.com/ 和 http://12.34.56.78/ 会被作为不同的域而区别对待,即使 www.abc.com 的 IP 地址实际上就是 12.34.56.78。此外,URL 中的任何路径表达式都将被忽略。例如,http://www.abc.com/~alice 会被识别为 http://www.abc.com/~malroy 的同源,从而忽略了这样一个事实,即这两个目录有可能属于不同的用户。
  • 大多数 Web 浏览器允许 Web 应用程序将域的定义放宽为应用程序自身的超域 :比如说,如果应用程序是从 www.abc.com 处下载的,那么应用程序可以把 document.domain 属性重写为 abc.com 或者就是 com(在 Firefox 中)。大多数最新的浏览器只允许访问已经把它们的 document.domain 属性重写为相同值的窗口或框架中的窗口对象。然而,一些版本比较老的浏览器允许与 document.domain 属性中指定的域建立 XMLHttpRequest 连接。
  • 即使某个 Web 服务器位于受信任的域中,该服务器可能并不是内容的始发源,尤其是在 Web 2.0 的上下文中 : 比如说,企业门户服务器、基于 Web 的邮件服务器或者 wiki 可以是受信任的,但是他们所托管的内容可能包含来自具有潜在的恶意的第三方的输入,这个第三方可以是跨站脚本(cross-site scripting,XSS)攻击(该攻击我们将在稍后介绍)的目标。因此,服务器所在的域并不能代表其内容的可信任度。

?

避免同源策略:JSON 和 动态脚本标记

由于 JSON 只是一种含有简单括号结构的纯文本,因此许多通道都可以交换 JSON 消息。因为同源策略的限制,我们不能在与外部服务器进行通信的时候使用 XMLHttpRequest 。JSONP(JSON with Padding)是一种可以绕过同源策略的方法,即通过使用 JSON 与 <script> 标记相结合的方法,如 清单 1 所示。


清单 1. JSON 例子

<script type="text/javascript"
  src="http://travel.com/findItinerary?username=sachiko&
  reservationNum=1234&output=json&callback=showItinerary" />
?

当 JavaScript 代码动态地插入 <script> 标记时,浏览器会访问 src 属性中的 URL。这样会导致将查询字符串中的信息发送给服务器。在 清单 1 中,所传递的是 usernamereservation 作为名称值对传递。此外,查询字符串还包含向服务器请求的输出格式和回调函数的名称(即 showItinerary )。<script> 标记加载后,会执行回调函数,并通过回调函数的参数把从服务返回的信息传递给该回调函数。

?