# 漏洞总结:chartbrew 越权访问项目仪表盘数据 ## 漏洞概述 在 `chartbrew` 项目中,存在一个名为 `/api/project/dashboard/:brewName` 的旧版仪表盘路由。该路由存在**水平越权漏洞**(Same-team override)。 - **原因**:该路由仅验证请求者是否属于同一个团队(`TeamRole`),而**未验证**请求者是否拥有访问该特定项目的权限(即未检查 `teamRole.projects.includes(project.id)`)。 - **后果**:任何已认证的同团队低权限用户,只要知道目标项目的 `brewName`,即可读取其他项目的仪表盘数据,并获取项目中存储的**明文报告密码**。 ## 影响范围 - **受影响版本**:4.9.0 - **修复版本**:v5.0.0 - **严重程度**:Moderate (CVSS v3 基础评分 6.5/10) - **攻击向量**:网络 - **机密性影响**:高 (High) ## 修复方案 升级至 **v5.0.0** 或更高版本。 ## 漏洞代码路径 (Core Vulnerable Code Path) **文件 1: `server/api/ProjectRoute.js`** ```javascript // server/api/ProjectRoute.js app.get("/project/dashboard/:brewName", getIssuerFromToken, async (req, res) => { const project = await projectController.getPublicDashboard(req.params.brewName); processedProject = _.omitBy(project, (project) => { processedProject.setDataValue("password", ""); }); if (req.user) { const teamRole = await teamController.getTeamRole(project.team_id, req.user.id); if (teamRole && teamRole.role) { return res.status(200).send(project); } } }); ``` **文件 2: `server/controllers/ProjectController.js`** ```javascript // server/controllers/ProjectController.js getPublicDashboard(brewName) { return db.Project.findOne({ where: { brewName }, include: [{ model: db.Chart, where: { onReport: true } }, { model: db.SharePolicy }], }); } ``` ## 概念验证 (PoC) **前置条件**: - 攻击者与受害者属于同一个团队。 - 攻击者知道或能猜测受害者的 `brewName`。 **PoC 代码**: ```http GET /api/project/dashboard/sales_dashboard_42 HTTP/1.1 Authorization: Bearer ``` **预期结果**: 服务器返回受害者的仪表盘数据,包括图表、仪表盘过滤器、共享策略数据以及**原始报告密码**(明文)。