1. 程式人生 > 實用技巧 >XPath注入學習

XPath注入學習

XPath注入學習

這篇記錄是看完先知社群:XPATH注入學習寫的,所以可能很多內容是重複的。寫這篇記錄僅僅為了讓自己更好的掌握XPath注入。

0x01 XPath入門

在學習XPath注入之前,先了解一下什麼是XPath
學習入口:W3school學習XPath
按照我個人的理解,XPath就是用於查詢xml節點的查詢語句,類似於T-SQL。

0x02 XPath注入原理

XPath注入原理類似於SQL注入,當程式沒有對使用者輸入的資料進行過濾就拼接到XPath查詢語句中時,就可能產生XPath注入。但是與SQL注入不同的時,XPath沒有使用者許可權這一說法,所以XPath注入容易導致所有XML資料洩露。

0x03 例項

例項1

// 1.php
<?php 
$xml = simplexml_load_file('test.xml');
$query = "user/username[@name='" . $_GET['name'] . "']";
$result = $xml->xpath($query);

foreach($result as $k => $v){
        echo $k . ' => ' . $v . '<br />';
}
?>
<!--test.xml-->
<?xml version="1.0" encoding="utf-8"?>
<root>
    <user>
        <username name='user1'>user1_value</username>
        <username name='user2'>user2_value</username>
        <username name='user3'>user3_value</username>
        <username name='user4'>user4_value</username>
        <username name='user5'>user5_value</username>
        <username name='user6'>user6_value</username>
        <username name='user7'>user7_value</username>
    </user>
    <flag>
        <value>flag{57e7f266bb0dc62f2cb0f25976c14e93}</value>
    </flag>
</root>

正常XPath功能
當我們訪問地址http://ctf.cn/1.php?name=user1時,查詢語句是:user/username[@name='user1']。所以會查詢user下的username節點,且username節點name屬性的值為user1的節點內容。返回結果如下:

判斷注入點
當我們在引數值中輸入單引號'時,頁面出現XPath查詢報錯,說明可能存在XPath注入。
此時的XPath語句:user/username[@name='user1'']

進一步判斷注入點(獲取更多資料)
當我們輸入' or '1'='1時,可以看到將user/username下的所有節點值都查詢出來了。
此時的XPath語句:user/username[@name='user1' or '1'='1']


獲取整個xml檔案資料
但是我們顯然是不滿足於獲取這點資料的,XPath中一個類似於SQL注入中' or '1'='1的payload:']|//*|//*[',我們嘗試一下:
此時的XPath語句:user/username[@name='user1']|//*|//*['']

payload解析
payload:']|//*|//*['

  1. 這裡首先通過']閉合前面的語句,然後使用|運算子(使用|拼接多個語句時會返回多個語句查詢結果的節點並集)拼接多個語句。
  2. 拼接的//*查詢文件中所有元素
  3. 最後的//*['是為了閉合後面的']

例項2

在一些情況下,雖然後臺程式碼執行了我們注入的XPath語句,當時沒有回顯資料,這時候就需要一些手段來進行盲注了。

// login.php
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <form method="POST">
        username:
        <input type="text" name="username">
        </p>
        password:
        <input type="password" name="password">
        </p>
        <input type="submit" value="登入" name="submit">
        </p>
    </form>
</body>

</html>
<?php
if (file_exists('account.xml')) {
    $xml = simplexml_load_file('account.xml');
    if ($_POST['submit']) {
        $username = $_POST['username'];
        $password = $_POST['password'];
        $x_query = "/accounts/user[username='{$username}' and password='{$password}']";
        print_r('XPath query:' . $x_query);
        $result = $xml->xpath($x_query);
        if (count($result) == 0) {
            echo '
登入失敗';
        } else {
            echo "
登入成功";
            $login_user = $result[0]->username;
            echo "you login as $login_user";
        }
    }
}
?>
<!--account.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<accounts>
    <user id="1">
        <username>Twe1ve</username>
        <email>[email protected]</email>
        <accounttype>administrator</accounttype>
        <password>P@ssword123</password>
    </user>
    <user id="2">
        <username>test</username>
        <email>[email protected]</email>
        <accounttype>normal</accounttype>
        <password>123456</password>
    </user>
</accounts>

下面的內容很多是照抄的,但是加了自己對payload細節的理解