Mashup 安全

保护 mashup 中的工件和数据的技术和技巧

mashup 开发模型为 Web 领域提供了各种可能性。然而,这种开放性导致了很多新的安全漏洞。本文将探讨解决部分这些漏洞的技巧和技术。

J. Jeffrey Hanson, 首席架构师, Max International

Jeff HansonJeff Hanson 有着 20 多年的软件行业从业经验,担任过 Microsoft Windows port OpenDoc 项目的高级工程师、Novell 的 Route 66 架构的主管架构师以及 eReinsure.com, Inc. 的首席架构师,指导了基于 J2EE 的再保险系统框架和平台的设计和实现。Jeff 目前是 Max Software, Inc. 的 CTO,他在指导为 Internet 安全和家长控制(parental controls)软件提供桌面和企业应用程序和平台。Jeff 写作了大量的文章和书籍,包括 .NET versus J2EE Web Services: A Comparison of ApproachesPro JMX: Java Management ExtensionsWeb Services Business Strategies and Architectures


developerWorks 投稿作者

2009 年 9 月 24 日

Mashup 是指使用来自各种(通常是公共的)来源的 UI 工件(artifacts)和数据构建的应用程序和 Web 页面。一个 mashup 开发模型在引入一个开放开发模型的同时也会带来许多新的安全风险。在开发一个 mashup 应用程序时,这些风险使安全问题浮出了水面。

常用缩略词

  • DMZ:隔离区(Demilitarized zone)
  • DOM:文档对象模型(Document Object Model)
  • HTML:超文本标记语言(Hypertext Markup Language)
  • HTTP:超文本传输协议(Hypertext Transfer Protocol)
  • SQL:结构化查询语言(Structured Query Language)
  • SSL:安全套接字层(Secure Sockets Layer)
  • UI:用户界面(User interface)

传统安全措施(比如 DMZ 和防火墙)在处理 mashup UI 工件和数据所需的细粒度访问时往往力不从心。一个 mashup 应用程序或页面必须处理跨站点请求伪造(Cross-Site Request Forgeries,CSRF)、Asynchronous JavaScript™ + XML (Ajax) 漏洞、跨站点脚本编写(XSS)和其他潜在的安全漏洞。

本文将探讨构建 mashup 应用程序和页面时应该解决的安全问题。

mashup 安全的必要性

Mashup 应用程序和页面使用来自一个或多个内部和外部站点的数据和 UI 工件共同构建,它们的构建方式往往很特别。这种开发模型会导致安全漏洞成倍增加:每当向一个 mashup 添加一个新的工件或数据源,安全漏洞都会增加。这种开放性集成要求确保这些工件和数据已经针对恶意入侵进行了测试和保护。

Mashup 页面也可以用于其它 mashup 的组件或数据源,这使得准确预测 mashup 工件、页面和数据源未来的使用方式变得很困难。因此,您必须事先解决 mashup 中的组件和流程的安全问题。

用户输入安全

如果使用一个综合的输入验证框架,许多输入漏洞,如 SQL 注入、CSRF 和 XSS,都是可以避免的。

一个 mashup 服务器端验证框架和一个 mashup 客户端验证框架应该在处理输入数据的方式上互相补充。由于客户端验证可以很容易地规避,因此,一个综合的、互补的服务器端验证为保护数据和流程提供了另一个关键组件。

一个有效的输入验证框架应当提供以下功能:

  • 定义一个限制输入数据的有限值列表;
  • 验证输入数据类型、数据长度、数据范围和数据格式;
  • 在客户机和服务器上使用正则表达式以维护一个统一的验证模型;
  • 审查输入数据中的无效字符。

避免按需脚本攻击

许多 mashup 中使用的一种技术是嵌入可以根据需要动态下载和解释的 JavaScript 代码段。按需脚本可能包含打算攻击 XXS 等安全漏洞的恶意代码。通过确保按需脚本被验证并确保从那些脚本生成的内容被适当编码以阻止恶意代码的执行,您可以避免这类漏洞。清单 1 提供了一个未编码的标记示例。

清单 1. 未编码的标记示例
  <div>
  This is example content
  </div>

上述代码段的编码版本如 清单 2 所示。

清单 2. 编码后的标记示例
  &lt;div&gt;
  This is example content
  &lt;/div&gt;

如上所示,使用动态生成的脚本的 mashup 页面必须确保一点:那些脚本生成的数据被验证并编码,以免浏览器将该数据解释为 HTML 标记或脚本代码。这种不小心的解释会导致恶意代码的执行和潜在的安全侵犯。

未经验证和编码的数据可能会遇到以下漏洞攻击:

  • 数据完整性受损
  • 入侵者创建或访问 cookies
  • 入侵者截获并访问用户输入
  • 恶意代码在一个受信任的域或上下文中执行

应该对每个被解释的上下文进行智能分析,以便可以处理那些会在特定上下文中导致问题的字符。

阻止会话固定(session fixation)

在服务器上验证一个用户之前,如果没有首先使现有会话失效,可能会导致所谓的会话固定。会话固定允许入侵者截获验证后的会话,或者创建新会话并捕获会话标识符。当一个合法用户使用这个会话标识符创建一个会话时,该会话标识符可能会被恶意使用。

清单 3 中的 Java™ 代码展示了验证一个客户机请求而没有首先使现有会话失效的例子。

清单 3. 会话固定漏洞示例
  private boolean authenticateUser(HttpServletRequest req)
  {
    // session.invalidate() should have been called prior to this
    // to invalidate an existing session

    HttpSession session = req.getSession(false);
    if (null != session)
    {
      // existing session assumed valid
      return true;
    }

    if (authenticateRequest(req) == true)
    {
      // create a new session
      req.getSession();
      return true;
    }
    
    return false;
  }

清单 3 展示了这样一种情况:一个现有会话没有被设置为失效,因此该会话被认为对当前请求有效。当一个新用户向服务器提供验证凭证时,这种情况可能会成为漏洞,因为只要会话有效,它就允许现有会话的发起人记录数据甚至可能利用数据发起攻击。

阻止这种类型的攻击的技术有:

  • 指定会话过期时间。
  • 使用显示的注销 UI 控件来提示会话失效。
  • 当需要保护隐私时,迫使用户重新输入凭证。
  • 对每个请求重新生成会话标识符。

一个 mashup 页面中的入侵者常常利用这种情况来绕开浏览器限制并重定向敏感数据,然后再记录这些数据。这种攻击称为跨站点脚本编写(cross-site scripting)

阻止 CSRF 攻击

CSRF 攻击由一个入侵站点的恶意代码发起,该代码欺骗浏览器,使其将无关的请求传输到一个受信任站点。浏览器的同源政策(SOP)并不阻止来自 不同来源的请求,而是只阻止传输 不同来源的站点的请求。因此,SOP 不能阻止 CSRF 攻击。

CSRF 攻击依赖于这样一个服务器假设:来自启动了验证会话的浏览器的所有请求都是有效的。典型的身份验证机制,如用户名/密码、cookies 和 SSL 证书,都不足以抵御 CSRF 攻击,因为这些机制依赖于验证浏览器和服务器之间的会话,而不是每个单独请求与服务器之间的会话。

在 CSRF 攻击过程中,请求来自一个入侵者站点,然后通过一个经过验证的浏览器页面传输到服务器。然后,服务器在不知情的情况下将响应传输回入侵者站点。CSRF 攻击过程中的请求和响应的序列如 图 1 所示。

图 1. CSRF 攻击过程中的事件序列
CSRF 攻击过程中的事件序列。图表显示了一个标签为 ‘Web Browser’ 的方框,其中包含一个 Mashup Page。一条虚线延伸到另一个标签为 ‘Intruder Site’ 的方框。另一条虚线延伸至右侧的标签为 ‘Mashup Server’ 的方框,其中包含 Mashup Platform。Web Browser 和 Mashup Server 之间的虚线的标签为 ‘authenticated session request/response’。

图 1 展示一个入侵者站点通过一个经过验证的 mashup 页面向一个 mashup 服务器发送请求。这种攻击只在一种情况下可行:入侵者站点使 mashup 页面为其将请求代理到企业 mashup 服务器。入侵者可以使用各种 HTML 技术进行这种攻击。

入侵者发动 CSRF 攻击所使用的一种技术是将一个 URL 嵌入到 <img> 标记的 src 属性中。当浏览器评估这个 <img> 标记时,这个 URL 将被引用。数据将被传输到该 URL 引用的主机。例如,注意下面的 <img> 标记:

<img src="http://mybank/transfer?amount=10000&fromaccount=44332&toaccount=55443">

如果 myback 对会话进行验证时,包含上述 <img> 标记的页面被访问,那么这个 <img> 标记将被评估并引用 src 属性中指定的 URL,从而启动被请求的动作。

如果 mybank 的服务器避免使用 HTTP GET 请求来发起更改,而是只使用 POST 来发起更改,那么您可以阻止这种类型的 DSRF 攻击。

mashup 服务器经常采用的一种阻止 CSRF 攻击的技术是要求每个 HTTP 请求都包含一个特定于请求的令牌,通过每个 POSTGET 请求一起传输到服务器。

JSON 数据安全

JavaScript Object Notation (JSON) 是一种遵守 JavaScript 编程语言语法的数据构造。因此,JSON 数据可以被几乎任何标准 JavaScript 函数或语句处理。特别是,eval() 函数可以而且经常用于处理 JSON 数据。

清单 4 是一个 JSON 数据块的简单示例。

清单 4. JSON 数据块示例
  [
    {
      name: "object1",
      message: "Greetings from object1",
    },
    {
      name: "object2",
      message: "Greetings from object2"
    },
    {
      name: "object3",
      message: "Greetings from object3"
      code: alert("This will be executed when evaluated!")
    },
    {
      name: "object4",
      message: "Greetings from object4"
    },
    {
      name: "object5",
      message: "Greetings from object5"
    }
  ]

当上述 JSON 数据被评估时,嵌入在对象 object3 中的 JavaScript 指令将被执行。这个特性经常被某些 mashup 服务器和应用程序利用,这些服务器和应用程序使用 JSON 作为针对 XMLHttpRequest 对象请求从服务器传回浏览器的响应的数据格式。但是,这种机制也暴露出一些严重的安全漏洞。

如上所述,当数据块被解释时,任何嵌入进 JSON 数据块中的 JavaScript 指令将立即执行。JavaScript 语言的 eval() 函数经常用于处理 JSON 数据,如以下的示例所示:

var jsonObject = eval('(' + httpReqResponse + ')');

JSON 数据块中嵌入的、通过 eval() 函数处理的指令将立即被执行。如果数据包含恶意代码,mashup 页面上的敏感数据就有可能落入恶意用户手中。而且,这个恶意代码还可能控制该 mashup 页面。

有几种技术可以防止 JSON 数据利用:

  • 在 JSON 数据块前面放置一个无限 while 循环。
  • 将 JSON 数据块封装到 JavaScript 注释中。
  • 避免使用 eval() 函数来处理 JSON 数据块。

清单 5 提供了一个在 JSON 数据块前面放置一个 while(1); 语句的示例。使用这种技术时,这个 while(1); 语句必须在使用该 JSON 数据之前在客户端上剥离,从而避免无限循环。

清单 5. 封装在一个 while 循环中的 JSON 数据示例
  while(1);
  [
    {
      name: "object1",
      message: "Greetings from object1",
    },
    {
      name: "object2",
      message: "Greetings from object2"
    },
    {
      name: "object3",
      message: "Greetings from object3"
      code: alert("This will be executed when evaluated!")
    },
    {
      name: "object4",
      message: "Greetings from object4"
    },
    {
      name: "object5",
      message: "Greetings from object5"
    }
  ]

您可以使用 JSON 库提供的 JSON.parse() 函数(参见 参考资料)来取代标准的 eval() 函数。清单 6 提供了使用 JSON.parse() 函数来处理 JSON 数据的示例。

清单 6. JSON.parse 函数示例
  <script type="text/javascript" src="js/json2.js"></script>
  var jsonObject = JSON.parse(httpReqResponse);

清单 7 展示了封装在 JavaScript 注释之间的 JSON 数据块。这些注释必须在使用 JSON 数据之前在客户端上剥离。

清单 7. 封装在 JavaScript 注释之间的 JSON 数据块示例
/*
[
  {
    name: "object1",
    message: "Greetings from object1",
  },
  {
    name: "object2",
    message: "Greetings from object2"
  },
  {
    name: "object3",
    message: "Greetings from object3"
    code: alert("This will be executed when evaluated!")
  },
  {
    name: "object4",
    message: "Greetings from object4"
  },
  {
    name: "object5",
    message: "Greetings from object5"
  }
]
*/

iframe 安全

Mashup 小部件通常作为嵌入式内联框架(iframes)被包含。iframes 是浏览器视为页面中的独立实体的 HTML 元素。由于放置在 iframe 中的内容不能在容纳它的 iframe 之外操作一个浏览器的 DOM 的任何部分,iframe 通常用作隔离一个 mashup 页面中具有潜在恶意的内容的 mashup 小部件和其他 UI 工件。

清单 8 展示了两个典型的 iframe 元素。

清单 8. 典型 iframe 元素示例
  <iframe src="http://jeffhanson.com/iframe1.html" />
  <iframe src="http://jeffhanson.com/iframe2.html" />

iframe 通常用作视觉元素,在浏览器页面中显示为带边界的 UI 组件。但是,iframe 通常是隐藏的,用作浏览器页面中的消息传递控件,如 图 2 所示。

图 2. iframe 和 mashup 页面之间的数据传递
这个图表先显示一个带有可见代码的 mashup 页面,然后显示一个执行其他功能的隐藏 iframe。

上图显示 jeffhanson.com/index.html 中的一个 HTML 页面。一个隐藏的 iframe 嵌入到该页面的 DOM 中并使用来自 jeffhanson.com/test.html 的内容构建。JavaScript 函数 sendData() 将这个隐藏的 iframe 的 src URL 设置为 http://jeffhanson.html#data。片段标识符(hash 标记)后面的 src URL 部分可以使用 window.location.hash 元素检索,正如为 onLoad 事件定义的函数所示。使用这种机制,这个隐藏的 iframe 可以在 index.html 页面加载时检索片段标识符后面的数据。这种技术常常用于在 iframe 之间或 HTML 页面和嵌入的 iframe 之间传输数据。

上述 iframe 数据传输机制同样会带来安全漏洞。由于 src URL 可以通过 HTML 页面中的任意组件设置,嵌入在页面中的包含恶意代码的 UI 工件将损害页面中包含的数据的隐私性,而且可能与发起主 HTML 页面的服务器进行通信。

您可以使用以下几种技术来阻止 iframe 片段标识符攻击:

  • 确保只有那些列入 “白名单” 的域可以修改片段标识符。
  • 使用公共密匙加密片段标识符。
  • 使用 JavaScript 代码过滤片段标识符。
  • 限制嵌入在片段标识符中的 JavaScript 代码,防止其意外执行。

结束语

Mashup 是使用来自各种(通常是公共的)来源的数据和 UI 工件构造的应用程序和 Web 页面。mashup 开发模型在一个非常开放的环境中运行,这带来了许多新的安全风险。这些风险使安全问题成为开发 mashup 应用程序时必须考虑的首要问题。

mashup 应用程序或页面必须解决 CSRF、Ajax 漏洞、XSS 和其他潜在的安全漏洞。传统安全措施(比如 DMZ 和防火墙)在提供 mashup 开发需要的安全保障方面往往力不从心。本文讨论了构建 mashup 应用程序和页面时遇到的安全问题。

参考资料

学习

获得产品和技术

  • JSON.org 查找关于 JSON 和您需要的库的更多信息。
  • 下载 IBM 产品评估版 并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development
ArticleID=430651
ArticleTitle=Mashup 安全
publish-date=09242009