🔴 Admin 严重问题

以下问题可能导致数据泄露、安全风险或资金损失,需优先修复。

🔴 A01 ✅ 已修复 安全 · users 模块

用户密码哈希返回给前端

API:GET /admin/users/:id
源码位置:Financial_Admin/server/routes/admin.js — users 列表查询
问题描述:后端 SELECT 语句包含 password_hash 字段并将完整 bcrypt 哈希值返回给前端。虽然前端可能不渲染该字段,但数据已通过 HTTP 响应传输,存在被中间人攻击或日志泄露的风险。
根因分析:SQL 查询未使用 SELECT columns EXCEPT (password_hash) 或明确列举字段,而是使用了 SELECT * 或包含 password_hash 的完整字段列表。
影响范围:任何能访问 GET /admin/usersGET /admin/users/:id 的 Admin 账户均可获取任意用户的密码哈希。攻击者若拿到哈希可尝试离线暴力破解(bcrypt cost factor 低时更脆弱)。
改进建议:
  1. 后端 SQL 查询明确排除 password_hash
    SELECT id, phone, nickname, ..., created_at FROM users WHERE ...
  2. 或在后端响应前删除该字段:delete result.password_hash
  3. 提高 bcrypt cost factor 至 12
风险评级:高 — 若 admin 账户被攻破,攻击者可批量获取用户密码哈希进行撞库攻击。
🔴 A02 ✅ 已修复 安全 · system 模块

SMTP 密码明文存储在数据库

API:GET /admin/email-config · PUT /admin/email-config
源码位置:Financial_Admin/server/routes/admin.js — email-config 路由
问题描述:SMTP 密码以明文存储在 system_config 表中(key = email_smtp),GET 接口直接将包含密码的完整配置返回给前端。任何 Admin 账户均可通过该接口获取 SMTP 明文密码。
修复进度:
  1. ✅ GET /admin/email-config:返回时将 smtp.pass 替换为 ********
  2. ✅ PUT /admin/email-config:提交密码为 ******** 或空时,保留原密码不更新
  3. ❌ 数据库中仍为明文存储(未做 AES-256 加密)
根因分析:smtp.pass 字段在数据库中未加密,PUT 时也是直接存储明文。生产环境中 SMTP 密码通常是邮箱授权码或重要凭据。
影响范围:获取 SMTP 密码后,攻击者可:以系统名义发送欺诈邮件、监听本应发给用户的通知邮件、利用 SMTP 服务器发送垃圾邮件(产生费用或导致 IP 被封禁)。
改进建议:
  1. SMTP 密码在数据库中加密存储(AES-256),密钥由环境变量持有
  2. GET /admin/email-config 返回时隐藏密码:smtp.pass = '********'
  3. 修改密码时才传输明文,存入前加密
🔴 A03 安全 · api-keys 模块

AI API Keys 以明文存储在数据库

API:POST /admin/api-keys · GET /admin/api-keys
源码位置:Financial_Admin/server/routes/admin.js — api-keys 路由(约 L1041-1052)
问题描述:用户提交的 API Key(OpenAI/Claude 等)通过 POST /admin/api-keys 存入数据库时,字段名为 api_key_encrypted,但实际存储的是明文值(非加密)。字段名具有误导性,让人误以为已加密。管理员在前端即可查看完整 API Key 明文。
根因分析:INSERT 语句直接将 req.body.api_key 存入 api_key_encrypted 列,未进行任何加密处理。
影响范围:任何 Admin 账户可获取所有用户的 AI API Key,可能产生大量未经授权的 AI API 消费(费用由用户承担)。
改进建议:
  1. 使用 AES-256-GCM 加密存储 API Key,密钥由环境变量持有
  2. GET 返回时解密用于调用,解密后不落盘
  3. 前端仅显示 Key 的后 4 位:********abcd
  4. 或者:让用户自己管理 Key,Admin 仅记录使用量
🔴 A04 数据安全 · transactions 模块

CSV 导入执行全量 DELETE,数据不可恢复

API:POST /api/transactions/:billId/upload(Analyzer 后端)
问题描述:上传 CSV 文件后,后端执行 先删后插 策略:先 DELETE FROM transactions WHERE bill_id = ?,再批量 INSERT 新数据。旧数据被不可恢复地删除。
影响范围:用户误上传、空文件上传、列错位上传都会导致历史交易数据全部丢失,无法恢复。
改进建议:
  1. 新增"追加模式"与"覆盖模式"两个选项(默认追加)
  2. 覆盖前自动备份旧数据到 transactions_archive
  3. 上传前做数据校验,校验失败则不删除旧数据