相信大家都非常熟悉 “注入”
这种攻击方式。 “注入”
这种攻击方式被列为了 OWASP 十大攻击的榜首。然而,本文所要讲述的不是被人熟知的SQL 注入攻击。而是相对较为冷门的 XPath 和 XQuery 注入攻击。
首先我们来了解一下什么是 XPath。
XPath 即为 XML 路径语言,是 W3C XSLT 标准的主要元素,它是一种用来确定 XML(标准通用标记语言的子集)文档中某部分位置的语言。
XPath 基于 XML 的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力,可用来在 XML 文档中对元素和属性进行遍历。
XQuery 是 XPath 语言的超集,增加了一些类似于 SQL 的语法和非常实用的函数来让我们更方便的查询 XML 文档。
关于 XPath 和 XQuery 的基本语法可以在 W3schools--XPath 里学习,链接如下:
http://www.w3school.com.cn/xpath/index.asp
说到这里大家可能会想到 SQL 注入了。
没错,XPath 注入的基本原理和 SQL 注入类似,发生在网站使用用户输入的信息构造 XPath 查询获取 XML 数据的时候。
通过发送精心构造的 Payload 至 web 服务器,攻击者可以获取 XML 数据的组织结构,或者访问在正常情况下不允许访问的数据,如果 XML 数据被用于用户认证,那么攻击者就可以提升他的权限。
由于 XPath 不同于其他的数据库查询语言,在其他的数据库中,一个用户可能只有权限能够访问某个数据库或者数据库中的某个表。
但是在 XML 中没有访问控制或者用户认证,如果用户有权限使用 XPath 查询,并且之间没有防御系统或者查询语句没有被防御系统过滤,那么用户就能够访问整个 XML 文档。
下面我将从这两个方面来分别演示这两种危害。
1.绕过验证
首先这里有一个登录身份验证的程序,所有的身份数据都存储在一个名为 UsersDataBase.xml
的文件里。 通过 XPath 查询 xml 文件,将用户提交的用户名和密码与 xml 文件中的用户名密码做比对来验证身份。
UsersDataBase.xml
的结构如下:
一般情况下,输入错误的用户名或密码会导致身份认证失败:
然而在后台的身份认证程序中有这样一句 XPath 查询语句
$xpath = "//users/user[username/text()='".$_POST["username"]."' and password/text()='".$_POST["password"]."']";
可以看到在 XPath 查询语句中并未对用户的输入做任何处理,这就直接导致一个注入点
我们可以构造如下的 payload:
Username: ' or '1' = '1
Password: ' or '1' = '1
那么整个 XPath 查询语句就变成了这个样子
$xpath = "//users/user[username/text()='' or '1' = '1' and password/text()='' or '1' = '1']";
整个查询语句恒成立,就直接导致了身份认证被绕过。
2.信息泄露
大多数情况下,当服务器返回数据时,都会对这些数据做一些处理。比如如果服务器返回一些错误信息,那么最终会被过滤掉,不会出现在用户的页面里。将尽可能少的信息暴露给用户,将可以提高安全性。但是即使错误信息被过滤掉,我们依然可以从服务器给出的不同返回结果推测出服务器做出了何种响应。作为攻击者可以提交一段包含 XPath 函数的 Payload,通过服务器给出的不同响应,判断得到我们想知道的信息。这就是 XPath 盲注。
下面这是一个通过用户名的ID来得到用户名的程序。当然具体场景也可能是通过名字来查询身份证号码等等,这里只做演示。
正常情况下,输入用户的 ID,就会得到相应的用户名。当查询语句恒成立时(如构造 Payload 为 ' or '1' = '1
时),就会返回第一个节点的用户名 “Alice”(这是程序本身的 bug )。而当查询语句错误或该 ID 在 xml 数据库中不存在时,就什么都不返回。
利用这点,我们就可以构造如下 Payload,比如:来查询整个 xml 文档的根节点的第一个字母是否为 “u”
' or substring(name(parent::*[position()=1]),1,1)='u
返回结果为 “Alice”,就说明整个 xml 文档的根节点的第一个字母是 “u”
,反之如果什么都没有返回,则说明根节点的第一个字母不是 “u”
。以此类推,我们就可以历遍整个 xml 文档了。这也是 xml 和其他数据库相比最大的威胁所在了,因为它没有访问控制和身份验证。
一开始就说到了,XPath 注入和 SQL 注入的原理是非常类似的,所以 XPath 的防御技术也完全可以借鉴防御 SQL 注入的方法。
具体方法有如下两种:
1、入口把关:
在数据处理之前,对用户提交的数据进行验证。
一是要验证是否包含特殊字符,像单双引号这类,可以对这类特殊字符进行编码转换或替换;
二是验证是否包含特定的 XPath 函数,可以过滤掉一些 XPath 函数,以提高安全性,当然了不能以牺牲用户体验或影响用户正常使用为前提。
2、控制出口:
在返回数据出口处屏蔽系统本身的错误提示信息。尽可能全的用自定义的错误信息替换系统本身的具体的错误信息。让攻击者对返回结果无规律可循,能有效防止被盲注。