各位好,我是安全研究人员,在研究 CRMEB 开源版代码时发现一个水平越权问题,已通过补天平台向厂商提交(审核中),同时在社区发帖反馈,希望推动 master 分支尽快修复。为避免被恶意利用,本帖只描述代码层面的成因与修复方式,不公开可直接照做的攻击请求。
【受影响版本】
CRMEB 单商户开源版(CRMEB-KY)v5.2 起(引入 /api/v2 路由后)至 v6.0.0。2026-09-22 拉取的 Gitee master 分支源码仍存在,未修复。
【成因(两处叠加)】
1. crmeb/app/api/controller/v2/user/UserInvoiceController.php 的 invoice() 方法调用服务层时漏传当前登录用户 uid(同文件内 delInvoice、setDefaultInvoice 均正确传入 (int)$request->uid(),唯此方法遗漏)。
2. crmeb/app/services/user/UserInvoiceServices.php 的 getInvoice(int $id, int $uid = 0):默认 $uid = 0 使 ($uid && $invoice['uid'] != $uid) 恒为假,归属校验被完全短路。
两者叠加后,任意已登录普通用户可通过自增 id 读取他人的发票记录,包含发票抬头、纳税人识别号、开户银行、银行账号、财务联系人电话/邮箱等企业敏感信息。
【同源缺陷】
crmeb/app/api/route/v1.php 第 329 行附近的积分订单详情接口 store_integral/order/detail/:uni 存在同样模式,可越权读取他人订单的收货人姓名、手机号、详细地址与核销码,建议一并排查。
【复现说明】
按官方仓库 help/docker 文档在本地 Docker 环境完整复现(未对任何线上站点做测试),复现材料已随补天报告提交。
【修复建议】
1. 控制器补传 uid:$this->services->getInvoice((int)$id, (int)$request->uid());
2. 服务层移除「默认 0 = 不校验」的危险设计,uid 改为必填,并在 DAO 查询条件直接带上 uid:$this->dao->getOne(['id' => $id, 'uid' => $uid, 'is_del' => 0]);
3. 全项目排查:凡服务层以「$uid = 0」作为跳过归属校验开关的方法,逐处核对调用方是否都传入 uid(建议全局搜索 int $uid = 0);
4. 临时缓解:对以自增 id 直接查询资源的详情接口增加频次限制与遍历检测。
愿意配合官方验证修复与复测。如有需要可私信沟通细节。

