今天的Web应用程序大量使用XML,在浏览器与前端应用程序服务器之间传送的请求和响应,以及在后端应用程序组件(如SOAP服务)之间传送的消息中都可以找到XML。如果使用专门设计的输入破坏应用程序的运行并执行某些未授权操作,这些位置就易于受到各种攻击。
在今天的Web应用程序中,XML常用于从客户端向服务器提交数据。然后,服务器端应用程序将处理这些数据,并且可能会返回一个包含XML或任何其他格式数据的响应。在使用异步请求在后台进行通信的基于Ajax的应用程序中,这种行为最为常见。浏览器扩展组件和其他客户端技术也可能会用到XML。
以一个使用Ajax实现的、提供无缝用户体验的搜索功能为例。在用户输入搜索词时,客户端脚本将向服务器提出以下请求:
服务器的响应如下所示(无论响应采用什么格式,其中都可能存在漏洞):
客户端脚本将处理该响应,并用搜索结果对用户界面进行更新。
如果遇到这种类型的功能,应当始终检查其是否存在XML外部实体(XXE)注入漏洞。之所以会出现这种漏洞,是因为标准的XML解析库支持使用实体引用。这些引用仅仅是在XML文档内部或外部引用数据的一种方法。通过阅读本书的其他内容,你应该很熟悉实体引用。例如,与<和>字符对应的实体如下所示:
XML格式允许在XML文档中定义定制实体。这些实体在文档开始部分的可选DOCTYPE元素中定义。例如:
如果文档中包含以上定义,解析器将用testrefvalue这个已定义的值替代文档中出现的任何&testref;实体引用。
此外,XML规范允许使用外部引用来定义实体,XML解析器将动态提取这些实体的值。这些外部实体定义采用URL格式,并可以引用外部Web URL或本地文件系统上的资源。XML解析器将提取指定URL或文件的内容,并将其作为已定义实体的值。如果应用程序在其响应中返回任何使用外部定义的实体的XML数据,则指定文件或URL的内容将在该响应中返回。
攻击者可以通过向XML添加适当的DOCTYPE元素,或通过修改该元素(如果它已经存在),在基于XML的请求中指定外部实体。外部实体引用使用SYSTEM关键字来指定,并使用URL(可能使用file:协议)进行定义。
在前一个示例中,攻击者可以提交以下请求(该请求定义一个引用服务器文件系统上的文件的XML外部实体):
收到这个请求后,XML解析器将提取指定文件的内容,并使用该内容来替代已定义的实体引用(攻击者已在SearchTerm元素中使用了该实体引用)。由于SearchTerm元素的值会在应用程序的响应中回显,这会导致服务器以该文件的内容作出响应,如下所示: