Kimdir01/econumo-multi-vuln-cve
GitHub: Kimdir01/econumo-multi-vuln-cve
针对 Econumo 个人理财应用的安全漏洞披露项目,记录了硬编码密钥、权限提升、弱加密等 6 个主要漏洞的 PoC 与修复建议。
Stars: 0 | Forks: 0
# GitHub 安全公告:Econumo — 硬编码 JWT 私钥、权限提升、弱加密、无 CSRF
## 公告信息
| 字段 | 值 |
|-------|-------|
| **严重程度** | 严重 / 高 |
| **CWE** | CWE-798 (硬编码加密密钥) / CWE-269 (权限提升) / CWE-916 (弱密码哈希) / CWE-352 (CSRF) |
| **CVSS v3.1** | 9.8 (硬编码 JWT 密钥) / 8.1 (权限提升) / 8.8 (无 CSRF) / 7.4 (弱哈希) |
| **CVSS 向量** | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
## 摘要
Econumo(基于 Symfony 5.4 的个人理财/预算应用程序)包含严重漏洞:(1) 代码库中硬编码了 JWT 私钥,导致可为任何用户伪造 token,(2) 损坏的 `canShareBudget()` 逻辑导致权限提升——任何用户无论角色如何均可共享预算,(3) 密码哈希仅使用 500 次迭代的 SHA-512(OWASP 建议 600,000+ 次),(4) 所有 50 多个表单全局禁用 CSRF,(5) “自动连接所有用户”功能将财务数据暴露给所有注册用户。
## 漏洞详情
### 受影响包/代码库
- **代码库:** Econumo
- **受影响版本:** 当前版本
- **已修补版本:** 无 (0-day)
**审计提交哈希:** `371a4b2352d7fa4ed114cd58078bce6a3ae98517`
## CVE-REQUEST-001:代码库中硬编码 JWT 私钥 (CVSS 9.8)
**文件:** `config/jwt/private.pem`
代码库中提交了一个私有的 RSA 密钥——用于 JWT token 签名:
```
config/jwt/private.pem
config/jwt/public.pem
```
**任何有权访问该公开代码库的人都可以为任何用户伪造有效的 JWT token。** JWT token 具有 30 天的 TTL。由于没有 token 吊销机制,伪造的 token 将提供长达 30 天的完整访问权限。
**PoC:**
```
import jwt, datetime
with open('config/jwt/private.pem', 'r') as f:
private_key = f.read()
token = jwt.encode({
'sub': 'admin@econumo.local',
'iat': datetime.datetime.utcnow(),
'exp': datetime.datetime.utcnow() + datetime.timedelta(days=30)
}, private_key, algorithm='RS256')
# 使用 token 以 admin 身份访问任何 API
```
## CVE-REQUEST-002:因 `canShareBudget()` 逻辑损坏导致的权限提升 (CVSS 8.1)
**文件:** `src/EconumoBundle/Domain/Service/Budget/BudgetAccessService.php`,第 110-122 行
```
public function canShareBudget(Id $userId, Id $budgetId): bool
{
try {
$role = $this->getBudgetRole($userId, $budgetId);
if ($role->isOwner() || $role->isAdmin()) {
return true;
}
} catch (AccessDeniedException) {
return false;
}
return true; // BUG: Falls through to TRUE for non-owner/non-admin!
}
```
任何具有任何级别预算访问权限的用户(甚至是“读者”)都可以与任意用户共享该预算。该函数对所有非所有者/非管理员角色返回 `true`,而不是 `false`。
## CVE-REQUEST-003:弱密码哈希 (SHA-512 / 500 次迭代) (CVSS 7.4)
**文件:** `config/packages/security.yaml`,第 3-6 行
```
password_hashers:
App\EconumoBundle\Domain\Entity\User:
algorithm: sha512
encode_as_base64: true
iterations: 500 # OWASP recommends 600,000+ for PBKDF2!
```
仅有 500 次迭代的 SHA-512 是极其不足的。商用 GPU 每秒可以测试数百万个密码。结合无密码强度策略(无最小长度、无复杂性要求)以及硬编码的 JWT 密钥,数据库泄露将导致离线密码被快速破解。
## CVE-REQUEST-004:无 CSRF 保护——所有表单均禁用 CSRF (CVSS 8.8)
**在所有 50 多个表单类中的模式:**
```
$resolver->setDefaults(['csrf_protection' => false]);
```
`src/EconumoBundle/UI/Controller/Api/*/Validation/*Form.php` 下的每一个表单类都明确禁用了 CSRF。受影响的操作包括:
- 创建/修改/删除交易
- 创建/修改/删除预算和预算限额
- 创建/修改/删除账户
- 创建/修改/删除分类
- 共享预算 / 授予访问权限
- 修改收款人
- 吊销用户访问权限
**PoC:**
```
```
## CVE-REQUEST-005:自动连接所有用户功能 (CVSS 7.5)
**文件:** `src/EconumoBundle/Application/UseCase/ConnectUsers/ConnectUsersEventHandler.php`
当 `ECONUMO_CONNECT_USERS=true` 时,每个新注册的用户都会自动连接到所有现有用户。由于连接会启用账户共享和预算访问,这会将所有财务数据暴露给每个注册者。
## CVE-REQUEST-006:生产环境错误响应中的堆栈跟踪 (CVSS 5.3)
**文件:** `src/EconumoBundle/UI/Service/Response/ResponseFactory.php`,第 54-56 行
```
if ($exception instanceof Throwable) {
$data['exceptionType'] = $exception::class;
$data['stackTrace'] = $exception->getTrace();
}
```
JSON 错误响应中暴露了完整的堆栈跟踪,包含文件路径、类名和方法签名。
## 其他发现(共 17 项):
| # | 漏洞 | CVSS | 类型 |
|---|--------------|------|------|
| 3 | JWT token 30 天 TTL(无刷新机制) | 6.5 | Session Mgmt |
| 4 | 通过密码重置进行用户枚举 | 5.3 | Enumeration |
| 9 | 认证 endpoint 上无速率限制 | 5.3 | Brute Force |
| 11 | 无密码强度验证 | 5.9 | Weak Policy |
| 12 | 用户名无输入验证 | 4.3 | XSS Risk |
| 13 | CORS 可能使用通配符(可配置) | 6.1 | CORS |
| 14 | 系统 API token 存在时序攻击风险 | 3.1 | Side-Channel |
| 15 | 分类替换 ID 存在跨用户风险 | 5.4 | IDOR |
| 16 | CSV 导入在未经验证下创建实体 | 4.3 | Resource Exhaustion |
| 17 | 错误响应中包含异常类名 | 3.3 | Info Disclosure |
## 影响
- 通过伪造 JWT 密钥实现**完全账户接管**
- 通过权限提升导致**财务数据泄露**(任何读者 -> 管理员)
- 通过弱哈希导致**密码被破解**(GPU 上每秒数百万次)
- 通过对所有交易的 CSRF 实施跨域**财务欺诈**
- 通过自动连接向所有用户暴露数据而造成**隐私违规**
- 通过堆栈跟踪导致**内部代码结构泄露**
## 补丁 / 修复
1. **立即执行:** 从代码库中移除 `config/jwt/private.pem`;为每次部署生成独立的密钥
2. 修复 `canShareBudget()` —— 将最后的 `return true` 更改为 `return false`
3. 用 bcrypt 或 argon2id 替换 SHA-512:`algorithm: bcrypt`, `cost: 12`
4. 启用 CSRF 保护:从所有表单中移除 `'csrf_protection' => false`
5. 默认禁用 `ECONUMO_CONNECT_USERS`
6. 将 JWT TTL 减少至 15-60 分钟,并实现 refresh token
7. 在认证 endpoint 添加速率限制
8. 添加最小密码长度(12+ 个字符)和复杂性要求
9. 从生产环境的错误响应中移除堆栈跟踪
10. 为系统 API token 添加常数时间比较
## 披露时间表
- **2026-06-28:** 由 Fatullayev Asadbek (Kimdir01) 发现所有漏洞
- **待定:** 报告给维护者
- **待定:** 通过 GitHub 请求 CVE
- **待定:** 发布公告
## 致谢
- 发现者:Fatullayev Asadbek | GitHub:Kimdir01
- 独立安全研究员
## 参考
- CWE-798:使用硬编码凭证 (Cryptographic Key)
- CWE-269:权限管理不当
- CWE-916:使用计算量不足的密码哈希
- CWE-352:跨站请求伪造
标签:JWT, PoC, Web安全, 协议分析, 暴力破解, 权限提升, 漏洞披露, 蓝队分析, 逆向工具