全部
常见问题
产品动态
精选推荐
功能建议

已处理 待处理 {{opt.name}}
已处理 待处理
分析中 已回复 待规划 {{opt.name}}
分析中 已回复 待规划
关于接口:api:store_list经纬度或被注入的修复

管理 管理 编辑 删除

CRMEB-BZ:门店列表 /api/store_list SQL 注入 — 漏洞说明与修改明细

============================================================


路径均相对站点 crmeb/ 根目录(与修复包内路径一致)。


----------------------------------------


一、修改了哪些文件(总览)

----------------------------------------


序号  |  修改文件  |  改动类型  |  修改位置(方法)  |  改了什么

1  |  app/dao/system/store/SystemStoreDao.php  |  修改方法  |  distance()  |  经纬度先 (float) 再拼进 SQL

2  |  app/api/controller/v1/PublicController.php  |  修改方法  |  store_list()  |  入参先经纬度校验再查库

3  |  app/api/controller/v1/PublicController.php  |  新增方法  |  checkCoordinate()  |  数值格式与 ±90/±180 区间校验

4  |  app/api/controller/v1/PublicController.php  |  文件头部 use  |  use crmeb\exceptions\ApiException;  |  供校验失败抛业务异常

5  |  app/api/ApiExceptionHandle.php  |  修改方法  |  render()  |  生产环境不再回显 SQL 等未预期异常原文

6  |  app/api/ApiExceptionHandle.php  |  文件头部 use  |  增加 HttpException、HttpResponseException;调试判断改用 $this->app->isDebug()  |  配合 render 分支


修复包内含 3 个文件:


crmeb/app/api/ApiExceptionHandle.php

crmeb/app/api/controller/v1/PublicController.php

crmeb/app/dao/system/store/SystemStoreDao.php


----------------------------------------


二、漏洞简述

----------------------------------------


GET /api/store_list?latitude=...&longitude=... 中,旧版把经纬度字符串直接拼进距离计算 SQL。攻击者可用 extractvalue / updatexml 做报错注入,外带 eb_system_config 里的云 AK 等敏感配置。


----------------------------------------


三、按文件 / 按位置的详细修改

----------------------------------------


文件 1:app/dao/system/store/SystemStoreDao.php


位置:distance() 方法(注入点本体)


项目  |  说明

5 月约行号  |  约第 40 行起

修复后约行号  |  约第 45 行起

谁调用  |  同文件 getStoreList()(约第 65 行):有经纬度时 $query->field(['*', $this->distance(...)])


改前(危险写法):


public function distance(string $latitude, string $longitude)

{

   return "(round(6367000 * 2 * asin(... ({$latitude} ... {$longitude} ...)))) AS distance";

}


用户输入原样进入 field() 原始 SQL 片段,框架不做参数绑定。


改后:


public function distance(string $latitude, string $longitude)

{

   $latitude = (float)$latitude;

   $longitude = (float)$longitude;


   return "(round(6367000 * 2 * asin(... ({$latitude} ... {$longitude} ...)))) AS distance";

}


方法注释中说明:返回值会进 SQL,必须先转 float。


改了什么地方(一句话):在 return 拼接字符串之前,增加两行强制 (float) 转换。


----------------------------------------


文件 2:app/api/controller/v1/PublicController.php


位置 1:文件头部 use 声明


* 新增:use crmeb\exceptions\ApiException;

* 原因:checkCoordinate() 校验失败时抛出业务异常。


位置 2:store_list() 方法


项目  |  说明

5 月约行号  |  约第 390 行起

修复后约行号  |  约第 394 行起

调用路由  |  GET /api/store_list(app/api/route/v1.php)


改前:


list($latitude, $longitude) = $request->getMore([

   ['latitude', ''],

   ['longitude', ''],

], true);

$data['list'] = $services->getStoreList(..., $latitude, $longitude);


$request 取值后直接传入服务层,无校验。


改后(在 getMore 与 getStoreList 之间插入):


$latitude = $this->checkCoordinate($latitude, 90, '纬度');

$longitude = $this->checkCoordinate($longitude, 180, '经度');

$data['list'] = $services->getStoreList(..., $latitude, $longitude);


改了什么地方(一句话):store_list() 里获取参数之后、调用 getStoreList() 之前,增加两行坐标校验。


说明:若本地另有注释掉 tengxun_map_key 的返回,属于额外改动,与 SQL 注入修复点不同;以你实际下发的 PublicController.php 为准。


位置 3:新增私有方法 checkCoordinate()


项目  |  说明

修复后约行号  |  约第 420 行起(紧接在 store_list() 之后)

5 月代码  |  无此方法


新增逻辑:


条件  |  行为

空字符串  |  返回 ''(不按距离排序)

非数值  |  抛 ApiException('{name}格式不正确')

超出 ±$max  |  抛 ApiException('{name}超出有效范围')

合法  |  返回 (string)(float)$value


$max:纬度传 90,经度传 180。


----------------------------------------


文件 3:app/api/ApiExceptionHandle.php


位置 1:文件头部 use


改前  |  改后

use think\facade\Env;(在 render 里读 debug)  |  增加 use think\exception\HttpException;
增加 use think\exception\HttpResponseException;
调试状态改为 $this->app->isDebug()


位置 2:render() 方法


项目  |  说明

5 月约行号  |  约第 79 行起

修复后约行号  |  约第 80 行起


改前(方法末尾):


对非业务异常(含数据库 DbException)直接:


return app('json')->fail($message, $massageData);


$message 可含 XPATH syntax error: '~密钥片段',造成报错外带。


改后(在原有 Api/Auth/Validate 分支之后增加):


1. HttpException / HttpResponseException → parent::render(...)(保持框架行为)。

2. 其它未预期异常:

  * 非 debug:return app('json')->fail('系统繁忙,请稍后再试');

  * debug:仍返回详细 $message(仅开发环境)。


改了什么地方(一句话):render() 末尾,给「数据库等未预期异常」增加生产环境脱敏分支,不再把 SQL 原文返回客户端。


----------------------------------------


四、修改位置速查(给实施同学)

----------------------------------------


SystemStoreDao.php

 └─ distance()

      └─ return 之前是否有 (float)$latitude / (float)$longitude   ← 必须有


PublicController.php

 ├─ use ApiException                                              ← 必须有

 ├─ store_list()

 │    └─ getMore 之后是否调用 checkCoordinate                     ← 必须有

 └─ checkCoordinate()                                             ← 必须有(新增)


ApiExceptionHandle.php

 └─ render()

      └─ 非 debug 时是否返回「系统繁忙,请稍后再试」              ← 必须有


----------------------------------------


五、三层防护对应关系

----------------------------------------


层级  |  文件  |  位置  |  作用

入口  |  PublicController.php  |  store_list + checkCoordinate  |  拒绝非数字 / 超范围参数

拼 SQL  |  SystemStoreDao.php  |  distance  |  强制 float,注入字符串变无害数字

回显  |  ApiExceptionHandle.php  |  render  |  生产不回显 SQL 报错内容


----------------------------------------


六、如何覆盖

----------------------------------------


1. 备份原三个文件。

2. 解压 zip,按路径覆盖到站点 crmeb/。

3. 确认 .env 中 APP_DEBUG=false。

4. 清缓存 / 重启 PHP-FPM。

5. 若日志已出现外带证据,立即轮换云 AK / 短信等密钥。


无数据库脚本。




附件

经纬度或被注入的修复.zip

{{voteData.voteSum}} 人已参与
支持
反对
请登录后查看

吴小汐 最后编辑于2026-11-02 14:43:31

快捷回复
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
回复({{post_count}}) {{!is_user ? '我的回复' :'全部回复'}}
排序 默认正序 回复倒序 点赞倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理员 企业

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推荐': '推荐'}}
{{item.is_suggest == 1? '取消推荐': '推荐'}} 【已收集】
{{item.floor}}# 沙发 板凳 地板 {{item.floor}}# 【已收集】
{{item.user_info.title || '暂无简介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打赏
已打赏¥{{item.reward_price}}
{{item.like_count}}
分享
{{item.showReply ? '取消回复' : '回复'}}
删除
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回复 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打赏
已打赏¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回复' : '回复'}}
删除
{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
收起 展开更多
查看更多
打赏
已打赏¥{{reward_price}}
204
{{like_count}}
{{collect_count}}
添加回复 ({{post_count}})

相关推荐

{{replySubmitting ? '提交中...' : '回复'}}
{{replySubmitting ? '提交中...' : '回复'}}
问题:
问题自动获取的帖子内容,不准确时需要手动修改. [获取答案]
答案:
提交
bug 需求 取 消 确 定
打赏金额
当前余额:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
请输入 0.1-{{reward_max_price}} 范围内的数值
打赏成功
¥{{price}}
完成 确认打赏

微信登录/注册

{{ wechatLoginError }}
切换手机号登录

{{ bind_phone ? '绑定手机' : '手机登录'}}

{{codeText}}
切换微信登录/注册
暂不绑定
CRMEB客服
CRMEB咨询热线 400-8888-794

扫码领取产品资料

功能清单
思维导图
安装教程
CRMEB开源商城下载 源码下载 CRMEB帮助文档 帮助文档
返回顶部 返回顶部
CRMEB客服