security-findings.md
3.9 KB
现网安全发现报告(xlyAi / saas ERP)
调查时间 2026-07-21。对象:saas-8s+ ERP 后端(
xlyEntry)+ xlyAi 现有 NL2SQL。 结论:后端不是权限权威,且现有 AI 取数路径存在越权与"读接口可写"风险。下述为供业务方决策的整改清单。
摘要(按严重度)
| # | 严重度 | 发现 | 影响 |
|---|---|---|---|
| 1 | 高 | 后端逐用户表单/菜单权限被故意关闭 | 任何登录用户经 API 可碰到 UI 里看不到的表单、可审核/删除全公司数据 |
| 2 | 高 | 通用读接口可被当写接口用 |
bUpdate=1 等参数经参数绑定触发存储过程改库存 |
| 3 | 高 | 现有 NL2SQL 无租户过滤、可跨品牌 | A 品牌用户"查所有客户"能拿到全部品牌数据 |
| 4 | 中 | NL2SQL 执行期无表白名单、SQL 安全仅部分 | 构造问题可 SELECT 任意视图;INTO OUTFILE/LOAD_FILE 未挡 |
| 5 | 中 | NL2SQL 流式缓存命中跳过校验、缓存无租户隔离 | 缓存投毒 / 越权复用 |
明细
1. 后端不是权限权威(表单级权限被关)
-
AuthorizationInterceptor里逐用户表单权限校验checkByUser(约 143–164 行)被注释,注释写着「朱总说不用放 20230626」。 -
getBusinessDataByFormcustomId及所有写/动作端点(add/update/delete/审核doExamine)只挂@Authorization=仅验登录。 - 后端只强制:公司级租户隔离(
sBrandsId/sSubsidiaryId)+ 行级jurisdiction数据范围。 - 逐用户表单/菜单权限只在前端 UI 按
sAuthsId过滤菜单。agent/脚本直接打 API 即绕过 UI → 越权放大。 - 说明:
sAuthsId的数据仍在(sysjurisdiction,由getsAuthsIdNew运行时算出,前端/getMenuList用),所以可在 agent 侧补回表单级白名单(xlyAi 已按此实现授权层,见docs/agent-architecture.md §7)。
2. 读接口可写
- 通用表单接口把请求体任意 key 按名绑定到存储过程 IN 参、无白名单。
- 例:
材料库存台账(SP_Inventory_InOutWarehouse,AI 已暴露)在bUpdate=1时真改MitMaterialsStore/EleMaterialsStock(重算并持久化库存)。 - 缓解:xlyAi 的 Read 工具只传分页/过滤参数,绝不透传
bUpdate/bUpdateAll(已实现)。根因需后端加参数白名单。
3–5. 现有 NL2SQL(XlyErpService.getDynamicTableSqlExec 链路)
- 无租户过滤:prompt 从不提品牌,代码不追加 WHERE,视图把品牌当普通列但不过滤;规则默认「返回全部数据」→ 跨品牌泄漏。
- 越权双轴:跨品牌(同上);跨表——工具权限只筛「喂给模型的表」,执行期无 allowlist,构造问题可查任意视图;系统管理员拿到全部工具。
-
SQL 安全仅部分:jsqlparser 挡了 Insert/Update/Delete/Drop + 关键字黑名单,但无正向 SELECT-only、
INTO OUTFILE未挡、LOAD_FILE未挡(\bLOAD\b≠LOAD_FILE)、无 LIMIT。本地账号 root 全权含 FILE。 -
流式缓存路径命中即跳过校验(
if isEmpty(cleanSql)兜底)+ 缓存无租户维度。
建议整改(优先级)
-
后端:重开逐用户表单权限校验(
checkByUser),或至少对 AI 服务账号强制表单白名单。 -
后端:通用读接口加参数白名单,禁止读路径接受写类参数(
bUpdate等)。 -
NL2SQL(新
queryData已按此实现):强制单条 SELECT、挡 OUTFILE/LOAD_FILE/系统库、强制 LIMIT、专用只读账号、AST 注入租户谓词、缓存过校验且按品牌隔离。 - 金融类数据:写操作/SQL 不可变审计(xlyAi 已建
ai_audit_log)。
注:xlyAi 侧已实现的缓解(授权层白名单、Read 参数白名单、
queryData安全栈、审计)是纵深防御,不替代后端整改(第 1、2 项根因在后端)。