文章总结: 文档披露某高校商城通过经纬度参数存在的SQL注入漏洞,攻击者利用距离计算接口未过滤输入直接拼接SQL查询,通过布尔盲注获取数据库root权限信息。关键发现包括漏洞成因(CRMEB框架参数未校验)、利用手法(distance字段作为回显通道)及风险(匿名访问+高权限)。可操作建议包括采用参数化查询、限制数据库权限、关闭错误回显等修复措施。 综合评分: 87 文章分类: WEB安全,漏洞分析,实战经验,安全开发,代码审计
经纬度里挖出个root:某高校商城SQL注入手记
原创
狗头安全 狗头安全
狗头网络安全
2026年6月12日 17:58 四川
在小说阅读器读本章
去阅读
从”附近门店”到”附近的数据库管理员密码”,中间就隔了一个单引号。
0x00 前言
前阵子测某高校的资产,翻到一个校园商城,CRMEB搭的。本来没抱多大期望——开源商城嘛,能有啥。
结果还真给我挖到了。而且挖出来的东西,怎么说呢,比我预期刺激得多。
漏洞已经报了,也确认修了,所以可以聊聊过程。
0x01 一个算距离的接口
商城有个”附近门店”功能,你传经纬度,它返回门店列表和到你的距离。接口长这样:
GET /api/xxxxx_list?latitude=30.476&longitude=114.343
返回里有个 distance 字段,单位米。没啥特别的,Haversine公式算球面距离
接口不需要登录,也不需要Token,公开的。
0x02 加个单引号
老规矩,先加个单引号:
GET /api/xxxxx_list?latitude=30.476&longitude=114.343'
我本来预期返回个400或者”参数错误”之类的。
然后它给我吐了这么一坨:
{
"status": 400,
"msg": "SQLSTATE[42000]: Syntax error or access violation: 1064
YouhaveanerrorinyourSQLsyntax...near''*pi()) /180) /2), 2)))))
ASdistance, `id`, `name`, `phone`, `address`, `detailed_address`..."
}
好家伙,Haversine公式的SQL实现原封不动甩我脸上了,连字段名都带着。
0x03 数值型,不用闭合引号
看报错就知道了,经纬度是直接拼进数学公式的,没有引号包裹。数值型注入,省心。
直接在经度后面减一个子查询试试:
GET /api/xxxxx_list?latitude=30.476&longitude=114.343-(SELECT 1)
正常请求distance是113米,门店就在校园里。加了(SELECT 1)之后,distance变成了7383707——七百多万米,7383公里。
经度被减了1,SQL老老实实地拿 113.343 去算了个到大西洋的距离。子查询执行了,注入坐实。
0x04 distance当信道:地球级别的布尔盲注
有了distance这个回显通道,布尔盲注就很自然了。构造一个CASE WHEN:
(SELECTCASEWHEN[条件为真]THEN100ELSE0END)
条件为真的时候经度偏100,distance大概1300多万;为假偏0,大概729万。阈值拉到1000万,大于就是TRUE,小于就是FALSE。
一个算”你离超市多远”的接口,被我拿来当了一台一次回答一个bit的应答机。
开始逐字符抠数据库版本:
@@version第1个字符是5吗? → distance=13225681 → 是
第2个字符是.吗? → 13225681 → 是
第3个字符是7吗? → 13225681 → 是
...
第5个字符是4吗? → 13225681 → 是
第5个字符是9吗? → 7295219 → 不是(对照组验证)
完整提取:@@version = 5.7.44-log
0x05 root
接下来提CURRENT_USER。同样的盲注手法,一个字符一个字符抠。
结果出来我愣了一下:
root@localhost
root跑业务库。
root权限意味着LOAD_FILE能读服务器文件,INTO OUTFILE能往磁盘写东西。再加上这个接口压根不需要登录——一个匿名可访问的接口,挂着root权限的数据库连接。
0x06 到此为止
只提了三条系统变量就收手了:
| 变量 | 值 |
| — | — |
| @@version | 5.7.44-log |
| CURRENT_USER | root@localhost |
| @@hostname | ****(脱敏) |
没碰业务数据。root权限+无认证+可执行任意SQL
0x07 为什么会这样
CRMEB的门店距离计算,SQL大概长这样:
SELECT*,
(2* ASIN(SQRT(
POWER(SIN((latitude -{用户纬度})* PI() / 180 / 2),2)+
COS(latitude * PI() / 180)* COS({用户纬度}* PI() / 180)*
POWER(SIN((longitude -{用户经度})* PI() / 180 / 2),2)
)))*6371AS distance
FROM store
ORDERBY distance
{用户经度} 和 {用户纬度} 直接拼进去的。没bindParam,没类型检查,连 is_numeric() 都没调一下。Haversine公式没问题,问题是拼接方式——你传数字它算距离,你传子查询它也照算。
这种写法在PHP里太常见了。开发可能觉得经纬度就是个浮点数,谁会往里面塞SQL呢?
我会。
0x08 怎么修
- 用PDO的bindParam做参数化查询,或者框架自带的查询构建器。手拼SQL属于是2026年了还在裸奔
- 经纬度做个范围校验,-180到180 / -90到90,超了直接拒。这俩参数的合法值域是固定的,没理由不卡
- 业务库别用root连。一个查门店距离的功能需要什么权限?SELECT就够了
- 生产环境关掉SQL报错回显。把完整错误信息返回给用户,等于开卷考试还附带参考答案
0x09 碎碎念
这个洞有意思的地方在于注入点藏在经纬度参数里。经纬度这东西,大部分人的直觉是”就一个小数”,不会往SQL注入上想。但只要参数进了SQL又没做处理,管你是经纬度还是用户名,该注的一样注。
另外distance做回显通道这个也挺有趣。不是经典的报错注入,不是时间盲注,是通过一个地理距离值的大小来传递true/false。从武汉到南极洲是真,到大西洋是假——大概是我见过地理跨度最大的布尔盲注了。
最后只通杀了两个学校,狠狠提交拿下某高校证书
本文仅作安全技术交流,漏洞已通过EDUSRC报送、。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:狗头网络安全 狗头安全 狗头安全《经纬度里挖出个root:某高校商城SQL注入手记》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论