XPath注入技术综述
一次完整的 XPath 注入攻击应该包括使用特殊构造的查询来提取一个 XML 数据库内的
数据或者信息。作为一门新的技术,XPath 注入在一定程度上和 SQL 注入漏洞有着惊人的相
似之处,通过下面的文字,我们将进一步来了解这种新型渗透技术。
在温习前人的相关研究成果之前,我们将介绍一些理论性的研究背景,这样有助于我们
更好地理解这种手法的关键。首先我们要了解的便是 XML 标准和 XPath 语言(XML 是 The
Extensible Markup Language(可扩展标识语言)的简写,是由全球信息网委员会(WWW)
推广并发展而来的) 。
所谓的 XML 文档就是通过 XML 的标准来对数据进行描述的一种形式,为了能更好地了
解 XML 的工作原理,我们用下面的这个例子来进行说明。
<?xml version="1.0"?>
//这一行显示的是 XML 的版本,当前是 1.0
<person> //描述 person 这一根元素
<name>Jaime</name>
<surname>Blasco</surname>
<govt_id_number private="if">
12345678w</govt_id_number>
<company>Eazel S.L</company>
//以上四行属于 person 的子元素,如 name、surname 等
</person> //该行是上面根元素的结束
大家可能已经注意到,XML 是一种允许快速、简易地提取并描述数据的语言,并且具
有简单直接等优点。知道了 XML 的工作原理,我们还需要一种特定的机制规范我们对这些
数据的利用,这是我们的 XPath 语言发挥作用的前提条件。
XPath 语言
XPath 是 XML 路径语言的简称,是通过“引用数据”的方式,从 XML 文档来读取各种
信息。 XPath 能够直接用于程序开发,比如微软的.net 和 Macromedia ColdFusion 这类框架对
XPath 缺省是支持的。 XPath 对现有 XML 文档的分段提取的方法主要是由 XML 分析器生成节
点树的形式来进行提取的。生成的树中包含有许多不同的节点,例如 source、element、
attribute、 text、comments、processing instruction 等。
关于 XPath,有一个很基本的要素就是表达式,作用相当于 XPath 的语言指令。这些表
达式代表着操作,其中最重要的一种便是路径表达式。比如“/person/name”,就是通过轮
流的方式遍历引用了全部的根元素及其下级的子元素。这样,XPath 表达式会返回一个空节
点列表或者包含一个或多个节点的元素列表。 XML 的另一个重要的机制是筛选,筛选是通过
谓词来实现的,通过谓词可以对匹配的节点进行进一步的筛选。比如
“/person/govt_id_number[@private=”if”]”,展示的是读取 person 中 govt_id_number 的
private 属性为 if 的下面所有子元素的集合。
此外,我们应该区分 XML 里面的条件运算符。And 运算符负责把不同的谓语封装进括
号中;or 运算符则代表管道字符“|” ;negation 则使用了保留字 NOT。如上面所叙述,我们
介绍的一些简单的 XPath 语法规则有助于我们理解后面将要列举的注入示例,因为这些规则
在程序实现的过程中发挥了巧妙的作用。
下面我们继续了解一些 XPath 语言的知识。我们可以使用双斜杠“//”来选择递减排列
下来的全部节点,如“//user/name”可以读取全部的用户名。此外,node()是另外一种在
XPath 中,读取任意节点的方法,如“//user/node() o //user/child::node()”,将读出任意用户
其下的所有节点(在这里,我们每个用户都有三个 text()类型的节点) 。同样,我们可以指定
相应的节点类型,比如 T ext()为文本节点,Comment()为注释节点,processinginstruction()可
以处理指令节点。
接下来我们将要介绍的语法部分就是最重要的谓语部分。比如
“//user[position()=n]/name”,这个表达式能够获得用户名称为 n 的节点;再比如
“//user[position()=1]/child::node()[position()=2]”,将读出第一个用户的第二个节点(这里是
password) 。
最后,我们通过介绍三个用来测试的有用的函数来结束这部分的讲述,它们分别是
count(node-set)函数,返回参数 node-set 中的节点个数,比如 count(//user/child::node()),将
会返回全部 user 的全部节点总数; stringlength(string)函数, 取字符串的长度,如果参数被省
略则计算上下文节点的 string-value 值的长度,比如
stringlength(//user[position()=1]/child::node()[position()=1]),将会返回 user 的第一个节点包含
的一个字符串的长度; substring(string, number, number)函数, 取子字符串,注意字符串的位
置从 0 开始,比如 substring((//user[position()=1]/child::node()[position()=1),2,1),将会返回 user
的第一个节点(name)的第二个字母。
分析有漏洞的程序
接下来我们将一起来研究一些隐含 XPath 注入漏洞的程序,这里的程序仅仅是用于教学
目的而编写的。在开始之前,我们要强调一下,本文的所有例子已经顺利通过 MONO 平台
下 C#的调试,因此可以方便地跨平台开发一些.net 软件。 Monodevelop 常常用于设计和 XSP
——一个轻型的并且支持 asp.net 程序的 Web 服务器。
我们看下面的示例(为了更好的熟悉我们接下来要分析的程序,以下将继续沿用下面的
这个 XML 文档作为例子) 。程序 index.aspx 的代码如下。
<%@ Page Language="C#" %>
<html>
<head>
<script runat="server">
void Button1_OnClick(object Source, EventArgs e){
System.Xml.XmlDocument XmlDoc = new System.Xml.XmlDocument();
XmlDoc.Load("datos.xml");
System.Xml.XPath.XPathNavigator nav = XmlDoc.CreateNavigator();
System.Xml.XPath.XPathExpression expr = nav.Compile(
"string(//user[name/text()='"+TextBox1.Text+"' and password/text()
='"+TextBox2.Text+"']/account/text())");
String account=Convert.ToString(nav.Evaluate(expr));
if (Check1.Checked) {
cadena.Text = expr.Expression;
} else {
string.Text = "";
}
if (account=="") {
Label1.Text = "Access Denied";
} else {
Label1.Text = "Access Granted\n" + "You have logged in as: "
+ account;
}
}
</script>
</head>
<body>
<body BGCOLOR="#3d5c7a">
<br clear="all">
<font color="white"><center>
<h3>Access to System:</h3></center>
<center><form id="ServerForm" runat="server">
<p>User:</p>
<asp:TextBox id="TextBox1" runat"server"></asp:TextBox>
<p>Password:</p>
<asp:TextBox id="TextBox2" runat="server"></asp:TextBox>
<p>
<button id=Button1 runat="server" OnServerClick="Button1_OnClick">
Enter</button>
<br>
<br>
<asp:CheckBox id=Check1 runat="server" Text="XPath Debug" />
<font color = "red"><h2><asp:Label id="Label1" runat="server">
</asp:Label></h2></font>
<span id=Span1 runat="server" />
</form>
</center>
</font>
<br clear="all">
<br><br><br>
<font color="#11ef3b">
<asp:Label id="cadena" runat="server"></asp:Label>
</font>
</body>
</html>
当我们连接到 XSP 服务器的时候,我们将看到如图 1 所示的页面, 这个页面模拟了一个
限制用户访问某些受限数据的验证界面(仅仅允许注册用户访问)。现在,让我们来思考一
下如何让程序非常规的运行,以使我们达到一定的目的。我们可以看到,上面有几个数据输
入的地方,像 username 和 password 这些,它们可以由字母和数字字符组成,甚至包括一些
特殊的字符。但是如果我们在用户名的地方输入一个普通的逗号,会发生什么情况呢?如图
2 所示。

图 1

图 2
我们要留意地是以下的代码:
System.Xml.XPath.XPathException:
Error during parse of string(//user[name/text()=''' and
password/text()='']/account/text())--->Mono.Xml.XPath.yyParser.yyException: irrecoverable
syntax error
由此我们可以知道程序是用.net 编写,并运行在 XSP(MONO)环境下,因为
Mono.Xml.XPath 泄露了这些信息。而且,在这种情况下,我们可以很容易地破坏该程序的
原有逻辑,因为这个错误提示页面已经把整个 XPath 查询完全暴露给我们:
string(//user[name/text()='' and password/text()='']/account/text())
那么我们不妨设想,当我们输入“' or 1=1 or ''='”来登录的话,又会出现什么情况?作
为一条查询,它将会是这样子:
string(//user[name/text()='' or 1=1 or ''='' and password/text()='']/account/text())
这样,我们特殊的输入导致了查询发生改变,这条查询语句将导致程序从 XML 文档读
取并返回第一个账户的名称。我相信,看过以上这些以后,不少人已经注意到这一类型的攻
击相比 SQL 注入攻击有一定的相似性,SQL 注入同样可以用于类似的程序,如:
Select * From users where name = '' and passwd = ''
攻击者会利用’ or 1=1-中的“-”来注释掉后面的查询语句。但是在 XPath 里,没有类似
的效果,因此我们必须另外找到一种机制来注释掉后面的那些查询“碎片”。我们很早就知
道我们的表达式“' or 1=1 or ''= –”利用了两个 or 运算符来取消掉 and 运算符的作用,从而
使得查询总是返回 TRUE 的结果。就这样,当我们输入上述字符串以后,我们将获得管理员
的访问权,因为管理员 administrator 是 XML 文档中的第一条记录。现在,作为一名用户,
我们已经获得了系统的访问授权,但除此以外,我们还能够做些什么呢?
获取 XML 数据库访问权
现在,可能你已经开始怀疑我们前面讲述的理论知识不仅仅是为了更好地理解这种攻
击,没错,从这里开始,我们要把我们的研究重心转移到获取整个 XML 数据库上面来。为
了实现这一目的,我们需要利用好我们仅有的工具,即 XPath 语言和程序对我们查询的各种
响应(包括那些授权或者未授权的访问,即我们分别看见的 TRUE 或者 FALSE)。举例子说明
一下,假设我们要得到第一个用户名的长度,输入:
' or string-length(//user[position()=1]/child::node()[position()=1])=4 or ''='
上面的意思是等于我们在碰运气一样地询问漏洞程序,第一个用户名是否由 4 个字符组
成。程序拒绝我们访问则表示程序对我们刚才的询问返回了否定的答案(false)。有了这个
机制,我们便可以尝试更多的可能性,最终将猜出长度为 5。
' or string-length(//user[position()=1]/child::node()[position()=1])=5 or ''=' //授权(返回
TRUE)
再来看另一个例子,我们要得到第一个用户的用户名的首字母,我们使用如下的查询:
' or substring((//user[position()=1]/child::node()[position()=1]),1,1)="a" or ''='
这次我们询问程序,第一个用户名称的首字母是否为 a,结果服务器返回 false。在若干
次可能性尝试以后,我们最终得到首字母为 j,服务器返回 true。
自动化处理
你或许觉得整个过程就是一个消耗大量时间并且十分烦琐的手工过程,但是,如果我们
能开发出一个小工具能够自动为我们干这些活的话,获取整个 XML 数据库绝对不成问题。
此外,由于我们这里的测试并非“盲”注入(因为我们事先已经了解了 XML 文档的结构),
所以我们很有可能更容易、快捷地开发自己相应的程序。
根据来自于程序的错误提示所提供的信息,我们可以重建 XML 文档的结构,比如下面
这样:
<user>
<name></name>
<password></password>
<account></account>
</user>
因此,我们的程序应该以递归的方式横跨所有的节点,并包括所有字符及其组合而成的
字符串。为了本次测试,我专门用 C#写了一个小程序,该程序能从本文所提到的示例程序
对应的 XML 文档中提取全部信息。
在编写我们自己的程序或者分析别人的程序的时候,我们应该事先熟悉该程序数据在鉴
定的过程中的传递。为了实现这一点,我们可以查看 HTML 源代码或者使用一个本地的代理
(如 WebScarab) 。例如以下的线索分析:
__VIEWSTATE=DA0ADgIFAQUDDgINAA4CBQEFCQ4CDQ0PAQEEVGV4dAFOJyBvciBzdHJpbmct
bGVuZ3RoKC8vdXNlcltwb3NpdGlvbigpPTFdL2NoaWxkOjpub2RlKClbcG9zaXRpb24oKT0xXSk9NCB
vciAnJz0nAAAAAA0NDwECAAABDUFjY2VzcyBEZW5pZWQAAAAADQ0PAQIAAAEAAAAAAA4BAQZD
aGVjazE%3D&TextBox1=test&TextBox2=test&__EVENTTARGET=Button1&__EVENTARGUMENT=H
TTP/1.0 200 OK
在以上的字符串里面,我们能够提取出许多变量,这些变量对于我们写的工具来说,在
连接服务器的时候是必不可少的。图 3 便是我们猜解程序运行时的截图。从中可以看到,为
了读取整个数据库,服务器必须响应数量庞大的请求包。但这不并构成什么问题,因为我们
可以改进自己程序的代码以降低查询请求包,以防我们遭遇某种二进制数据搜索的情况,或
者服务器被询问到给定的字符是在我们指定的字符之前还是之后的情况,使得程序也能应付
得来。我们暂时把这个任务留给有兴趣深入探讨的朋友。

图 3
如何防范这类的攻击
在本文的最后部分,我们将来一同探讨避免这一类或者类似的攻击的各种方法。在目前
许多防范这类攻击的方法中,过滤用户输入是其中十分有效的一种。过滤包括质疑一切用户
发送给我们程序的数据以及滤掉全部被认为是对我们程序有害的字符。过滤可以在客户端和
服务端两边实现,如果可能的话,建议两者同时进行过滤。
此外,目前还有一种方法便是参数化查询,查询中的表达式不会直接被执行,当应用了
参数化查询以后,这些查询会被重新编译执行,而不会随便让用户的输入直接在表达式中执
行,把用户的输入和程序的逻辑分离开了。最后一种办法就是使用专门被设计来针对这类型
攻击的一些产品,比如像由 Daniel Cazzulino 开发的一款安全防护工具。
总结
本文和大家讨论了 XPath 中的代码的注入攻击,随着 XML 技术的广泛传播和发展,一旦
程序使用了未受保护的 XML 和 XPath 规则,这类型的攻击将会严重威胁 web 安全。
XPath注入技术综述的更多相关文章
- XPath注入笔记
XPath注入 XQuery注入 测试语句:'or '1'='1 利用工具: Xcat介绍 Xcat是python的命令行程序利用Xpath的注入漏洞在Web应用中检索XML文档 下载地址:https ...
- xpath注入详解
0x01 什么是xpath XPath 即为 XML 路径语言,是 W3C XSLT 标准的主要元素,它是一种用来确定 XML(标准通用标记语言的子集)文档中某部分位置的语言. XPath 基于 ...
- 4.xpath注入详解
0x01 简介 XPath注入攻击是指利用XPath 解析器的松散输入和容错特性,能够在 URL.表单或其它信息上附带恶意的XPath 查询代码,以获得权限信息的访问权并更改这些信息.XPath注入发 ...
- XPath注入跟SQL注入差不多,只不过这里的数据库走的xml格式
SQL注入这块不想细聊了,相信很多朋友都听到耳朵长茧,不外乎是提交含有SQL操作语句的信息给后端,后端如果没有做好过滤就执行该语句,攻击者自然可以随意操纵该站点的数据库. 比如有一个图书馆站点book ...
- SQL注入技术专题—由浅入深【精华聚合】
作者:坏蛋链接:https://zhuanlan.zhihu.com/p/23569276来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 不管用什么语言编写的Web应用 ...
- SQL注入技术专题—由浅入深【精华聚合贴】
SQL注入技术专题—由浅入深[精华聚合贴] 不管用什么语言编写的Web应用,它们都用一个共同点,具有交互性并且多数是数据库驱动.在网络中,数据库驱动的Web应用随处可见,由此而存在的SQL注入是影响企 ...
- Android中通过进程注入技术改动广播接收器的优先级
前言 这个周末又没有吊事,在家研究了怎样通过进程的注入技术改动广播接收器的优先级.关于这个应用场景是非常多的.并且也非常重要.所以就非常急的去fixed了. Android中的四大组件中有一个广播:B ...
- 对Unity注入技术最简单的理解和应用
Unity注入技术,我决定最大的作用在于一个项目,尤其是WEB项目在更远其中一个类时,不需要重新生成,直接通过WEBCONFIG文件的修改就可以更改对应关系和功能,实验步骤如下: 1:新建一个接口IS ...
- 详解基于MSSQL “order by”语句报错的SQL注入技术
SQL注入,又名黑客技术之母,是一种臭名昭著的安全漏洞,由于流毒甚广,已经给网络世界造成了巨大的破坏.当然,对于该漏洞的利用技术,也是花样繁多,如访问存储在数据库中的数据,使用MySQL的load和i ...
随机推荐
- Splunk笔记
学习Splunk Fundamentals Part 2 (IOD) 和 Splunk Fundamentals Part 1课程的笔记. Chart Over By Tips: ….|chart c ...
- 常见协议基础知识总结--FTP协议
FTP协议是一种基于客户端和服务器的文件传输协议,属于应用层协议,基于传输层的TCP协议: FTP主要分成主动模式和被动模式两种传输方式, 方式是相对服务器而言的,服务器主动发起数据连接即主动方式,使 ...
- linux shell 脚本实现tcp/upd协议通讯(重定向应用)
linux shell 脚本实现tcp/upd协议通讯(重定向应用) http://www.cnblogs.com/chengmo/archive/2010/10/22/1858302.html
- 【POI2017||bzoj4726】Flappy Birds
外国人很良心的啊,这题比NOIP那题还简单…… 不用管他最后的位置,因为移动的次数肯定是恒定的,所以维护在每一个柱子的位置能飞到的范围,递推下去即可. #include<bits/stdc++. ...
- Java坦克大战 (二) 之画一个能动的圆圈代表坦克
本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...
- Winform 中panel的mousewheel鼠标滚轮事件触发
如果将窗体或容器控件(如Panel控件)的AutoScroll属性设置为True时,那么当窗体或Panel容不下其中的子控件时就会出现 滚动条,通过移动滚动条可以上下显示出窗体或Panel中的全部内容 ...
- WEB字体,多列布局和伸缩盒
WEB字体 语法 @font-face{ font-family:""; src:url() format() ... } 兼容性写法 @font-face { font-fami ...
- oracle 一行转多行
比如sql: select zyxdm from table where bindid=2265254 查询结果为:1|4|8|9|10 将这个查询结果转成多行,结果如下: ID 1 4 8 9 10 ...
- python日志模块笔记
前言 在应用中记录日志是程序开发的重要一环,也是调试的重要工具.但却很容易让人忽略.之前用flask写的一个服务就因为没有处理好日志的问题导致线上的错误难以察觉,修复错误的定位也很困难.最近恰好有时间 ...
- JWT是什么?
# 转载请留言联系 什么是JWT? Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的 ...