本文是有关ebXML安全性的两篇文章中的第二篇。在第一篇文章消息交换中,我们分析了消息层安全性和ebXML消息的安全性策略。即,第一篇文章关注这样一个事实,实际的有效负载可以通过签名和加密来提供持久安全性、数据隐私和ebMS消息审计能力。正如先前所讨论的,这种有效负载保护超越了传输层机制(例如SSL或者TLS)所提供的级别。这种类型的消息层安全性属于trust enablement类,该类允许消息包含已签名和加密的有效负载,而不考虑传输。
本文的主要目的是关注一种新的内容威胁类别,称为XML内容攻击。这些攻击依靠的是XML有效负载的可执行性特性和ebMS消息中代码插入和强制分析尝试的容量。正如我们所看到的,即使是标题加密、签名、传输层安全性等对策也不足以确保不受这些类型的业务威胁的攻击。
定义XML内容攻击 XML 内容攻击是任何类型的基于XML的内容携带的威胁,该威胁具有以下一种或者几种能力:
导致处理的应用程序崩溃或者发生故障,出现拒绝服务状态(DoS)。
强制处理的应用程序执行恶意的或者多余的代码,或者强制处理应用程序之后的任何下游实体执行恶意的或者多余的代码。
为了了解如何保护应用程序不受XML内容攻击的破坏,我们首先必须了解在处理XML(特殊情况下,还有ebMS)时将发生什么事。
普通ebMS消息处理 当传输并随后处理ebMS消息的时候,即使使用经过加密的有效负载,仍然存在未加密的外部结构和元数据始终需要处理。这种外部结构是SOAP标题和正文,以及ebMS消息标题和清单。此处发生的处理操作在通常情况中包含XML分析和XML语法验证。
分析步骤是所有类型的XML处理的基本先决条件,第二个步骤涉及到schema验证,该步骤确保在将消息传递到下游实体之前符合必要的SOAP和ebMS规范。通过使用验证分析程序,一些实现可以同步执行分析和验证。
schema验证步骤涉及到使用W3C兼容的schema,以验证收到的XML消息的语法。对ebMS来说,主要的SOAP消息依靠两种schema,SOAP v1.1结构和标题,以及ebMS 2.0定义的清单扩展。图1是相关的步骤简图。
图1.典型ebMS标准的XML处理配置。 在图1中,ebMS 2.0消息进入贸易合作伙伴的B2B网关,并在网关中接受分析和随后验证。图中还说明了B2B服务器依靠两种schema定义(XSD文档),SOAP v1.1 schema和ebMS 2.0 schema。两种schema都可以在schema验证过程中使用,以执行内容模型检查和防止异常请求的破坏。
正如我们将在下面章节中看到的那样,这种标准配置对于XML内容攻击来说是存在漏洞的,即使遵循schema验证步骤。
ebMS 2.0内容攻击
大多数XML安全性方面的新手会认为使用schema验证步骤防止XML内容攻击的破坏绰绰有余。例如,schema验证要求根据标准schema精确地检查ebMS 2.0消息。如果发送了任何类型的异常请求,schema验证步骤将失败,并且消息将立即被拒绝。不幸的是,这种推理不正确,因为在标准schema(包括ebMS 2.0)中使用了可扩展性点。
在schema中,extensibility point是一个通用术语,指开放内容模型。开放内容模型就是允许将来自外部名称空间的内容存放在XML有效负载中,同时仍可以维护schema有效性。换句话说,消息根据外来内容的存在,使用标准schema来维护有效性。在schema中存在可扩展性点的原因是schema有效性不代表安全特性,而代表语言语法验证特性。当语言具有一种开放内容模型的时候,这主要说明语言的有效实例可以包含意外的或者外来的内容。
开放语言内容模型允许schema具有可扩展性和前瞻性。不幸的是,正是这种可扩展性对于希望使用XML实现安全业务交易的合作伙伴来说是一个巨大的、开放性的漏洞。
为了查看扩展点是如何使用ebMS,有必要首先看看根据ebMS 2.0 schema定义的内容模型。以下示例和定义基于这一位置提供的标准ebMS 2.0 schema:
http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd
ebMS 2.0内容模型 如前文所述,如果我们需要了解其扩展点是如何操作的,则我们必须研究ebMS 2.0内容模型。要做的第一件事情是查看ebMS 2.0 schema是如何定义的。对启动程序来说,因为ebMS依赖于SOAP v1.1,所以schema定义是根据SOAP扩展点定义的。尤其是,元素结构的BNF语法式样视图如清单1所示。该结构使用标准的基数符号(cardinality symbol),即,星号(*)代表零或者多,问号(?)代表零或者一,加号(+)代表一或者多,不存在只代表一项的符号。为了提高透明度,这里已省略名称空间。
清单1. SOAP/ebMS元素结构
<Envelope>
<Header>
<MessageHeader>
<From>
<To>
<CPAId>
<ConversationId>
<Service>
<Action>
<MessageData>
(<DuplicateElimination>) ?
(<Description>) *
</MessageHeader>
<Header>
<Body>
(<Manifest>
(<Reference> +
(<Schema>) *
(<Description>) *
</Reference ) +
</Manifest> ) ?
<Body>
</Envelope>
前一内容模型说明了ebMS的外部结构。ebMS消息的Schema有效实例需要至少具有所示的结构和基数规则(cardinality rule)。清单1全面地描述了维护schema有效性所需的最低要求,但是没有说明各种扩展点。ebMS中的很多元素schema类型定义允许插入任意内容。例如,考虑如清单2所示的以下两种Manifest元素示例。同样,为了提高透明度,这里已省略名称空间。
清单2:两种Schema有效的Manifest元素
ebMS Manifest Schema有效实例A
<Manifest id="Manifest" version="2.0">
<Reference id="pay01" xlink:href="cid:payload-1"
xlink:role="http://regrep.org/gci/purchaseOrder">
<Schema location="http://foo.com/po.xsd" eb:version="2.0"/>
<Description>
Purchase Order for 100,000 widgets
</eb:Description>
</eb:Reference>
</eb:Manifest>
ebMS Manifest Schema有效实例B
<Manifest id="Manifest" version="2.0">
<Reference id="pay01" xlink:href="cid:payload-1"
xlink:role="http://regrep.org/gci/purchaseOrder">
<Schema location="http://foo.com/po.xsd" eb:version="2.0"/>
<Description>
Purchase Order for 100,000 widgets
</eb:Description>
<Garbage a="1" a="2" a="3" a="4" a="5" a="6" ...>
<Garbage>
<Garbage>
<Garbage>
<Garbage>
<Garbage>
<Garbage>
<!-- lots and lots of text here -->
</Garbage>
</Garbage>
</Garbage>
</Garbage>
</Garbage>
</eb:Reference>
</eb:Manifest>
在这一点上,非常明显,清单2所示的ebMS消息B中可能存在外来的危险内容。此处添加的外部内容只是一个小小的示例,实际上数百兆字节的外部数据可能会用于连接XML处理资源。此外,如果添加了奇怪但格式完整的内容(例如插入深层嵌套的属性或者代码),则可以利用某些分析程序中的单点弱点。
读者在此也许会提出异议,即注意到,由于XML Signature的作用,整个标题都可以受到保护,这使插入任意XML内容变得不可能。该参数无效的原因是文档必需在签名得到验证之前进行分析。在使用传统签名的二进制格式文档中,这种情况可能始终不会出现;签名可能首先被处理。但是,在XML的情况中,XML Signature本身就是XML。因此,首先进行的就是XML分析,这意味着在签名验证进行之前,分析程序最终必须处理文档的整个节点集,所以攻击将在签名验证过程开始之前或者签名验证过程进行中开始,而永远不会在签名验证过程完成之后开始。
清单2的要点是schema验证和XML Signature都不能防止如实例B所示的外部内容的破坏。其原因在于ebMS 2.0消息规范中的可扩展点。尤其是,Reference元素被定义为可扩展,并允许以一种毫无限制的方式添加来自外部名称空间的任何元素。用于提供这种可扩展性的schema定义机制被称为any元素,在使用该元素的schema中它是主要的安全性漏洞之一。请参见清单3以获取Reference的schema定义片断。
清单3:Reference元素的Schema定义
<element name="Reference">
<complexType>
<sequence>
<element ref="tns:Schema" minOccurs="0" maxOccurs="unbounded" />
<element ref="tns:Description" minOccurs="0" maxOccurs="unbounded" />
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
</sequence>
<attribute ref="tns:id" />
<attribute ref="xlink:type" fixed="simple" />
<attribute ref="xlink:href" use="required" />
<attribute ref="xlink:role" />
<anyAttribute namespace="##other" processContents="lax" />
</complexType>
</element