XPath注入及盲注

author: Melody

XPath注入

1.描述
类似于SQL注入,XPath注入发生在当站点使用用户输入的信息来构造请求以获取XML数据。攻击者对站点发送经过特殊构造的信息来探究站点使用的XML是如何构造的,甚至进一步获取正常途径下无法获取的数据。当XML数据被用作账户验证时,攻击者还可以提升他的权限。
通过XPath查询XML,XPath是一种简单的描述性的声明以允许XML请求确定一些信息在XML中的位置。(或许相当于路径查询)。类似于SQL,寻找信息时你可以指定特定的属性和特征来匹配相应的信息。当为网站使用xml时一般都会接受一些形式的字符串请求来确认内容的位置并将相应的内容展示到页面上。这个输入必须经过审查(类似于sqli中的waf)以确保不会返回错误的数据。
XPath是一种标准语言,它的语法一般是独立的,这意味针对它的攻击可以是自动化的(有工具没),在这一方面同SQL注入没有区别(sqlmap),因为这里不存在访问控制,所以我们不会遇到许多在SQL注入中经常遇到的限制。(访问权限等等)

2.漏洞示例

我们以这个xml片段举例。
<?xml version=”1.0” encoding=”utf-8”?>



Arnold
Baker
ABaker
SoSecret
Admin


Peter
Pan
PPan
NotTelling
User


假设我们有一个网页用户验证系统使用了这个xml中的数据,每当需要查询用户名密码的时候,软件都会通过XPath来查询用户,下面是两种语言的实现案例。

VB:
Dim FindUserXPath as String
FindUserXPath = “//Employee[UserName/text()=’” & Request(“Username”) & “‘ And
Password/text()=’” & Request(“Password”) & “‘]”

C#:
String FindUserXPath;
FindUserXPath = “//Employee[UserName/text()=’” + Request(“Username”) + “‘ And
Password/text()=’” + Request(“Password”) + “‘]”;
其中//Employee[UserName/text()=’” & Request(“Username”) & “‘ And Password/text()=’” & Request(“Password”) & “‘],就是XPath查询语句。我们来解析一发。(这里不是原文)

//代表匹配节点,选择文档中的元素而不考虑元素的位置,这里顺带一提,/代表从根节点选取,这里也可以这样写/Employees/Employee[UserName/text()=’” & Request(“Username”) & “‘ And Password/text()=’” & Request(“Password”) & “‘]
具体实例参考http://www.w3school.com.cn/xpath/xpath_syntax.asp

当用户正常输入用户名与密码的时候这段XPath表达将生效,但是攻击者可能构造一个无效的用户名和密码并且选中特定的xml节点而不需要知道用户名与密码是什么,也就绕过了登录。如果选中了根节点,可直接暴露xml存储的所有数据
(这段是我的想法,也不是原文)

案例:
Username: blah’ or 1=1 or ‘a’=’a
Password: blah
那么之前寻找用户名与匹配的密码的XPath脚本就变成了//Employee[UserName/text()=’blah’ or 1=1 or ‘a’=’a’ And Password/text()=’blah’]通过构造两个or以绕过and,还有另一个技巧是使用’’=’’(这个我看别的文章看来的别打我。。。)
在这个条件下,密码将与验证条件无关,而用户名又恒真,所以绕过。
防御技术先不翻译了。其实有些文章已经被翻译过了,我坚持再来一次是想在这个过程中思考,不那么浮躁。
防御就先不说了,一切输入都是有害的!
https://www.owasp.org/index.php/XPATH_Injection

XPath盲注
一般的XPath注入需要看页面返回的错误信息来判断xml的结构,盲注则是在页面不返回错误信息的时候判断True or False,从而推断页面结构。而这和SQL盲注又是及其类似的。

案例
攻击者为了制造一起成功的攻击可能会使用两种方法,一种是Boolenization,另一种是XML Crawling。通过向XPath语法中添加额外的表达来达到攻击的目的。

1.Boolenization
使用Boolenization方法,攻击者会判断他所输入的XPath表达式返回的结果是真还是假。让我们假设攻击者的目标是登录进一个web应用,一个成功的登录应该会返回True而失败则相反。只有很小的一部分内容可以用于分析。当攻击者将精力集中在一串字符串上,他可能会测试每一个单词来看看这字符串属于哪一个类(这里不很懂)

代码
<?xml version=”1.0” encoding=”UTF-8”?>


admin
test
SuperUser


rezos
rezos123
Simple User


函数
Function:
string.stringlength(//user[position()=1]/child::node()[position()=2]) 返回地一个用户的第二个子节点(child node)的值的长度(这里为8)
substring((//user[position()=1]/child::node()[position()=2),1,1) 返回这个用户的用户名的地一个字母。

2.XML Crawling
为了得到XML文档结构,攻击者可能使用一些XPath内建功能:
(1)count(expression)
例子:count(//user/child::node())这个返回user后节点的数目
(2)stringlength(string)
例子:string-length(//user[position()=1]/child::node()[position()=2])=6
使用这个请求,攻击者可以得到是否第一个用户的第二个节点password的长度是否为6(和SQL盲注非常像有木有)
(3)substring(string, number, number)
例子:substring((//user[position()=1]/child::node()[position()=2]),1,1)=”a”
挺好懂得吧?用于确认第一个user的password的地一个字母是否为a。这个函数中的地一个number用于指定字符串截取开始位置,第二个number用于制定字符串的长度。缺省的话会怎么样呢?自己试试。

显然这个工作量巨大~自然需要写脚本进行啦~~~
参考资料:https://www.owasp.org/index.php/Blind_XPath_Injection

以上是翻译加自己理解混合体,有错误希望指正。
Melody 2015.12.8
在咚咚咚提醒下修改了部分表述 2015.12.8

推荐一篇论文:http://dl.packetstormsecurity.net/papers/bypass/Blind_XPath_Injection_20040518.pdf

最后解析一下这次HCTF关于XPATH的题目,这题比较简单。虽然也有盲注的成分在,但是几乎等于没有了。还记得上面说的吗,在XPath里面没有权限的说法,注入几乎畅行无阻。
http://120.26.93.115:24317/0311d4a262979e312e1d4d2556581509/index.php?user=user1这个是题目地址,首先加入%27测试一下,发现页面空白,使用and关键字再用//*匹配所有字符仍然返回空白页面,于是再加上一个and user[user=%27user9来闭合整段字符串,按理说应该出来了,结果还是返回空白页面,考虑到可能过滤符号,使用url编码,可能过滤关键字,将and替换为|,于是构造出http://120.26.93.115:24317/0311d4a262979e312e1d4d2556581509/index.php?user=user1%27]|//*|user[user=%27user9,所有关键词被匹配~得到flag hctf{Dd0g_fac3_t0_k3yboard233}
问题,最后一个user9改成100,条件已经为否,为什么在and并列条件下仍然能够返回所有node?
我自己的理解:XPath在这里使用的是简单的匹配,他所返回的除了数据应当就是null,那么在这里第三个条件就等于不返回数据,而前两个条件是返回数据的,所以就通过喽~