软件供应链安全:源代码缺陷实例剖析
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.7 XQuery注入

2.7.1 XQuery注入的概念

XQuery是一种函数式语言,用于检索以XML格式存储的信息,负责从XML文档中查找和提取元素及属性。使用XQuery可在网络服务中提取信息,生成摘要报告,进行数据转换等。XQuery与XPath十分相似,许多XML查询很难做到像XPath这样简便、清晰、准确的表达。XQuery可以解决XPath的局限性,但复杂性略有增加。类似于XPath注入,XQuery注入攻击利用了XQuery解析器的松散输入和容错特性,能够在URL、表单或其他信息上附带恶意代码进入程序。当包含恶意代码的信息参与动态构造XQuery查询表达式,就会造成XQuery注入,攻击者可以利用漏洞获得权限信息的访问权并更改这些信息。本节分析XQuery注入产生的原因、危害以及修复方法。

2.7.2 XQuery注入的危害

发生XQuery注入,攻击者可能会访问存储在敏感数据库中的信息,获得被入侵服务器的配置信息。

2.7.3 实例代码

本节使用实例的完整源代码可参考本书配套资源文件夹,源文件名:XQueryInjection.java。

1)缺陷代码

上述代码的目的是获取用户输入的用户名、密码,并在XML文档中查询该条数据是否存在。在第23行获取XML的数据源对象,在第24~25行获取用户输入的用户名和密码,在第26行进行XML数据源连接,在第27行动态构造XQuery查询表达式,在第29行通过XQPreparedExpression类准备执行XQuery查询,在第30行执行XQuery查询。由于用户名和密码来自不可信任的数据源,因此在正常情况下如果想要搜索用户名和密码的对应账户,执行的表达式如下:

但是,这个表达式是由一个常数查询字符串和用户输入字符串连接并动态构造而成的,因此只有在username或password不包含单引号字符时,才会正确执行这一查询。如果攻击者为username输入字符串admin'or 1=1 or''=',那么该查询会变成:

添加条件admin'or 1=1 or''='会使XQuery表达式永远评估为true。因此,该查询在逻辑上等同于更简单的查询:

无论输入什么样的密码,查询结果集都会返回文档中存储的管理用户,这样的查询可使攻击者绕过用户名与密码同时匹配的要求。

2)修复代码

上述修复代码的第27~29行使用declare语法声明字符串变量username和password。在第31行、第32行调用XQExpression对象的bindString()方法。该方法的作用为把变量绑定到XQuery查询中。该操作类似于SQL查询中使用占位符来进行参数化查询,参数化查询可以避免SQL注入,在这里声明变量来模拟参数化查询,一定程度上可以避免注入的产生。

2.7.4 如何避免XQuery注入

(1)使用参数化的查询,如/root/element[@id=$ID]。

(2)创建一份安全字符串列表,限制用户只能输入该列表中的数据。

(3)净化用户输入,fn:doc()、fn:collection()、xdmp:eval()和xdmp:value()函数需要特别注意,使用时需过滤'、[、=和&等特殊字符。