0x00 什么是XPath
XPath是W3C的一个标准。它最主要的目的是为了在XML1.0或XML1.1文档节点树中定位节点所设计。
目前有XPath1.0
和XPath2.0
两个版本。
XPath1.0
Xpath1.0是1999年成为W3C标准,而XPath2.0标准的确立是在2007年。
XPath是
一种表达式语言
,它的返回值可能是节点,节点集合,原子值,以及节点和原子值的混合等。
Xpath2.0
XPath2.0
是XPath1.0
的超集。
它是对XPath1.0的扩展,它可以支持更加丰富的数据类型,并且XPath2.0保持了对XPath1.0的相对很好的向后兼容性,几乎所有的XPath2.0的返回结果都可以和XPath1.0保持一样。
XPath 1.0 和 XPath 2.0 之间的区别包括:
- 基于序列而非节点集的新的数据模型
- 绑定变量的能力,以前的变量绑定在宿主语言(XSLT)中
- 完全支持 XML Schema 数据类型
- 很多新功能,包括
正则表达式、日期/时间和字符串操作
- 注释,虽然不是一个重要的特性,但是在调试查询时很方便:测试时可以注释掉路径的一部分
具体案例如下,由于开发水平有限,用的也比较少,写起来实在蛋疼,这里就不多写了。
https://www.ibm.com/developerworks/cn/xml/x-wxxm35.html
0x01 Xpath表达式语法
XPath
使用路径表达式来选取XML
文档中的节点或节点集。节点是通过沿着路径 (path)
或者步 (steps)
来选取的。
路径
位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。
在两种情况中,位置路径均包括一个或多个步
,每个步
均被斜杠分割:
- 一种是绝对路径
/step/step/...
- 一种是相对路径
step/step/...
步
步(step
)有以下几种
名称 | 定义 |
---|---|
轴(axis) | 定义所选节点与当前节点之间的树关系 |
节点测试(node-test) | 识别某个轴内部的节点 |
谓语(predicate) | 更深入地提炼所选的节点集 |
step
的语法:
轴名称::节点测试[谓语]
常见轴的名称
轴可定义相对于当前节点的节点集。
轴名称 | 结果 |
---|---|
ancestor | 选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute | 选取当前节点的所有属性。 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点。 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
谓词(筛选表达式)
XPath
的谓词
即筛选表达式,类似于SQL
的where
子句。
运算符/特殊字符 | 说明 |
---|---|
/ | 此路径运算符出现在模式开头时,表示应从根节点选择。 |
// | 从当前节点开始递归下降,此路径运算符出现在模式开头时,表示应从根节点递归下降。 |
. | 当前上下文。 |
… | 当前上下文节点父级。 |
* | 通配符;选择所有元素节点与元素名无关。(不包括文本,注释,指令等节点,如果也要包含这些节点请用node()函数) |
@ | 属性名的前缀。 |
@* | 选择所有属性,与名称无关。 |
: | 命名空间分隔符;将命名空间前缀与元素名或属性名分隔。 |
( ) | 括号运算符(优先级最高),强制运算优先级。 |
[ ] | 应用筛选模式(即谓词,包括"过滤表达式"和"轴(向前/向后)")。 |
| | 两个节点集合的联合 |
- | 减法。 |
div | 浮点除法。 |
and, or | 逻辑运算。 |
mod | 求余。 |
not() | 逻辑非 |
= | 等于 |
!= | 不等于 |
< ,>,>=,<= | 特殊比较运算符 |
0x02 XPath学习测试
XML 实例文档
<data>
<users>
<user>
<name id='1'>hacker</name>
<message>Hello hacker</message>
<password>cisco123</password>
</user>
<user>
<name id='2'>admin</name>
<message>Hello admin</message>
<password>s3cr3tP4ssw0rd</password>
</user>
</users>
</data>
PHP代码
//$x为上面的xml代码
<?php
$xml=simplexml_load_string($x);
$xpath = $_POST['name'];
print $xpath."<hr>";
$res = ($xml->xpath($xpath));
print_r($res);
}
?>
测试用例
选择文档根下面的所有元素节点,即根节点(XML文档只有一个根节点)
user下所有的节点
user下的第一个节点
user下的最后一个节点
users下的第一个节点递归下降查找所有的文本节点(无限深度)
第一个users节点下的所有子节点
user节点下name为admin的节点
user节点下name的属性名为id,且为1的节点
了解得差不多了,就不在继续了,暂时够用了。
0x03 XPath注入
案例1——web_for_pentester靶场
源码
$x = "<data><users><user><name>hacker</name><message>Hello hacker</message><password>pentesterlab</password></user><user><name>admin</name><message>Hello admin</message><password>s3cr3tP4ssw0rd</password></user></users></data>";
$xml=simplexml_load_string($x);
$xpath = "users/user/name[.='".$_GET['name']."']/parent::*/message";
$res = ($xml->xpath($xpath));
while(list( ,$node) = each($res)) {
echo $node;
}
万能密码走一波hacker' or 1='1
,不过这里也没想明白为什么true
就可以打印所有了。。。这个学起来真是麻烦,还没找到学习方法啊,好多不知道为啥的,心累。
当然还可以直接遍历所有的元素'] | ../..//* | //*%00
,如果不能截断,那就用['
闭合。
(这里也有点奇怪,我的php是5.5怎么还能用截断!!!???。。。神奇了)
案例2——XVWA
由于是post
提交的,所以我这里用burpsuite
来进行提交,方便编码。
这样能爆出所有的节点,编码以后是1']|..//*
,然后后面截断%00
多余的就可以了
盲注
这里找了一篇不错的文章,感觉用起来好困难,不想努力了,找了个偷懒的方法。
先放文章好了,XPath Hacking技术科普
我自己拿了个xcat
的工具,用起来还可以,直接在python
下安装就可以直接使用了。
直接跑出了所有的数据,然后我通过查看日志,把所有的payload
都看了下,是使用的盲注
,常用函数为
- count()
- lower-case()
- boolean()
- string-length()
- substring-before()
- comment()
- …
总之还有很多,跑出上面的结果一共用了1364
次请求,下面解释几个用的多的函数
-
Count(NODESET)
– 返回节点集中子节点的数目 -
String-length(STRING)
–返回指定字符串的长度,获得一个节点名的长度可以使用以下语法: string-length(/[1]/[1]/name()) -
Substring (STRING, START,LENGTH)
– 这个功能用来枚举一个节点的文本值,我们可以使用substring
匹配指定字符串与节点中的字符串,可以循环的通过实体字符表获取所有字符的值。
盲注技巧记录
XPath从当前节点可以导航到父节点或一个特定的子节点。
例如,使用子字符串技巧,提交如下 格式的密码,提取当前节点的父节点的名称:
' or substring(name(parent::*[position()=1]),1,1)='a
若有结果返回,则说明节点的第一个字母为’a’,则继续测试第二个字母:
确定address节点的名称后,攻击者就可以轮流攻击它的每个子节点,提取出它们的名称与值。(通过索引)
//address[postion()=3]/child:node()[position()=4]/text()
查找XPath漏洞
渗透步骤
好了,我认输了,这个暂时就这样了,以后有收获了再更新!