一、什么是逻辑漏洞?大白话解释
逻辑漏洞 = 程序员写代码时逻辑考虑不严谨,导致攻击者能钻空子
和SQL注入、XSS这些技术型漏洞不同,逻辑漏洞不是代码写错了,而是业务逻辑设计有缺陷。
逻辑漏洞的危害:0元购事件
想象一下:
• 你在电商平台买东西,本来要付100元
• 但你抓包修改了价格参数,改成0.01元
• 系统没校验,直接让你用1分钱买到了商品
这就是真实的"0元购"事件,商家损失惨重!
二、越权漏洞:水平越权 vs 垂直越权
概念区分
| 类型 | 解释 | 举例 |
|---|---|---|
| 水平越权 | 同级别用户之间互相访问 | 张三登录后,能看到李四的个人信息 |
| 垂直越权 | 低权限用户获得高权限 | 普通用户登录后,能执行管理员操作 |
三、水平越权实战(Pikachu靶场)
靶场搭建
1. 下载 Pikachu 靶场
2. 放到 phpStudy 的 WWW 目录下
3. 修改 inc/config.inc.php 配置数据库
4. 访问 http://localhost/pikachu/install.php 初始化
5. 访问 http://localhost/pikachu/ 进入靶场
漏洞复现
靶场地址:
http://localhost/pikachu/vul/overpermission/op1/op1_login.php
第一步:正常登录
点击"提示"获取账号密码,用 test 账号登录。
登录后看到个人信息页面,URL 类似:
http://127.0.0.1/pikachu/vul/overpermission/op1/op1_mem.php?username=test&submit=点击查看个人信息
第二步:水平越权
直接修改 URL 中的 username 参数:
http://127.0.0.1/pikachu/vul/overpermission/op1/op1_mem.php?username=kobe&submit=点击查看个人信息
刷新后,页面显示的是 kobe 的个人信息!
漏洞原因 :服务器只检查了用户是否登录,没检查当前用户是否有权查看 username 对应的信息。
四、垂直越权实战(Pikachu靶场)
漏洞复现
靶场地址:
http://localhost/pikachu/vul/overpermission/op2/op2_login.php
目标:用普通用户账号,执行管理员操作(添加用户)
第一步:普通用户登录
用 test 账号登录,只能查看用户列表,没有添加用户的权限。
第二步:尝试直接访问管理员页面
访问:
http://127.0.0.1/pikachu/vul/overpermission/op2/op2_admin.php
系统提示需要管理员登录。
第三步:找到管理员操作接口
通过目录扫描或源码分析,发现管理员添加用户的接口:
http://127.0.0.1/pikachu/vul/overpermission/op2/op2_admin_edit.php
第四步:垂直越权成功
用普通用户登录状态,直接访问这个接口:
http://127.0.0.1/pikachu/vul/overpermission/op2/op2_admin_edit.php
竟然可以添加用户!
漏洞原因分析
查看源码 op2_admin_edit.php:
<?php
// 只检查了是否登录,没检查是否是管理员!
if(isset($_SESSION['user'])) {
// 执行添加用户操作
// ...
}
?>
问题 :代码只判断了用户是否登录(isset($_SESSION['user'])),没判断用户是否是管理员角色!
五、业务逻辑漏洞:0元购/1元购
案例1:商品编号篡改
场景:购买商品A,但实际扣费的是商品B(更便宜的那个)
攻击方式:
1. 选择一个便宜商品(比如1元的优惠券)
2. 抓包记录商品ID
3. 选择一个贵商品(比如5000元的手机)
4. 抓包修改商品ID为便宜商品的ID
5. 用1元的价格买到了5000元的手机
案例2:金额数据篡改
场景:直接修改支付金额
攻击方式:
POST /pay HTTP/1.1
...
product_id=123&price=5000&quantity=1
用 Burp Suite 抓包,修改 price 参数:
POST /pay HTTP/1.1
...
product_id=123&price=1&quantity=1
如果后端没校验价格是否匹配商品,就能用1元买5000元的商品!
案例3:数量篡改
场景:购买负数数量的商品
POST /pay HTTP/1.1
...
product_id=123&price=100&quantity=-1
如果计算总价时没考虑负数:
$total = $price * $quantity; // 100 * (-1) = -100
可能导致账户余额反而增加了!
六、支付漏洞实战案例(大米CMS)
漏洞1:直接修改商品价格
参考案例:wooyun-2016-0226613
步骤:
1. 选择一个5400元的手机,抓包:
index.php?m=Member&a=gobuy&iscart=0&id=69&name=大米CMS手机开发专版&qty=1&price=5400>ype=灰色
1. 再选择一个6000元的手机,抓包
1. 把5400元手机的请求数据包替换到6000元的请求
1. 6000元的手机变成5400元了!
漏洞2:修改支付状态
有些系统在支付成功后会设置一个状态字段:
POST /pay HTTP/1.1
...
order_id=123&status=0
直接改成:
POST /pay HTTP/1.1
...
order_id=123&status=1
系统可能直接把订单标记为"已支付"!
七、逻辑漏洞防御方法
1. 越权漏洞防御
| 防御措施 | 具体做法 |
|---|---|
| 权限校验 | 每个操作都要检查当前用户是否有权限 |
| 用户身份绑定 | 从Session获取当前用户ID,不从参数获取 |
| 角色验证 | 关键操作前验证用户角色是否匹配 |
安全代码示例:
<?php
// 不安全:从参数获取用户ID
$user_id = $_GET['user_id'];
$data = getUserData($user_id);
// 安全:从Session获取当前用户ID
$user_id = $_SESSION['user_id'];
$data = getUserData($user_id);
// 安全:操作前验证权限
if($_SESSION['role'] != 'admin') {
die('权限不足!');
}
// 执行管理员操作
?>
2. 支付漏洞防御
| 防御措施 | 具体做法 |
|---|---|
| 服务端计算价格 | 不信任前端传的价格,根据商品ID从数据库查价格 |
| 价格签名验证 | 前端传价格时带签名,后端验证签名 |
| 数量校验 | 数量必须大于0且小于库存上限 |
| 支付状态校验 | 支付状态由支付回调接口设置,不信任用户输入 |
安全代码示例:
<?php
// 不安全:直接用前端传的价格
$price = $_POST['price'];
$total = $price * $_POST['quantity'];
// 安全:从数据库查价格
$product_id = $_POST['product_id'];
$price = getPriceFromDB($product_id); // 从数据库获取真实价格
$quantity = intval($_POST['quantity']);
// 校验数量
if($quantity <= 0 || $quantity > $product['stock']) {
die('数量不合法!');
}
$total = $price * $quantity;
?>
八、逻辑漏洞速查表
| 漏洞类型 | 漏洞原理 | 攻击方式 | 防御方法 |
|---|---|---|---|
| 水平越权 | 未校验数据归属 | 修改用户ID参数 | 从Session获取当前用户ID |
| 垂直越权 | 未校验用户角色 | 直接访问高权限接口 | 操作前验证角色 |
| 0元购 | 未校验价格 | 修改价格参数 | 服务端查库计算价格 |
| 数量篡改 | 未校验数量范围 | 修改数量为负数 | 校验数量 > 0 |
| 支付状态篡改 | 未校验支付来源 | 修改支付状态 | 由回调接口设置状态 |
总结
逻辑漏洞的核心特点:
1. 不是代码错误,是业务设计缺陷
2. 往往需要理解业务流程才能发现
3. 危害可能比技术漏洞更大(直接造成经济损失)
记住一句话:永远不要信任用户输入的任何数据,关键操作必须在服务端重新校验!