介绍逻辑漏洞
逻辑漏洞就是指攻击者利用业务的设计缺陷,获取敏感信息或破坏业务的完整性。一般出现在密码修改、越权访问、密码找回、交易支付金额等功能处。其中越权访问又有水平越权和垂直越权两种,如下所示。
- 水平越权:相同级别(权限)的用户或者同一角色中不同的用户之间,可以越权访问、修改或者删除其他用户信息的非法操作。如果出现此漏洞,可能会造成大批量数据的泄露,严重的甚至会造成用户信息被恶意篡改。
- 垂直越权:就是不同级别之间的用户或不同角色之间用户的越权,比如普通用户可以执行管理员才能执行的功能。
逻辑缺陷表现为设计者或开发者在思考过程中做出的特殊假设存在明显或隐含的错误。精明的攻击者会特别注意目标应用程序采用的逻辑方式,并设法了解设计者与开发者可能做出的假设,然后考虑如何攻破这些假设,黑客在挖掘逻辑漏洞时有两个重点:业务流程和HTTP/HTTPS请求篡改。
常见的逻辑漏洞有以下几类。 - 支付订单:在支付订单时,可以篡改价格为任意金额;或者可以篡改运费或其他费用为负数,导致总金额降低。
- 越权访问:通过越权漏洞访问他人信息或者操纵他人账号。
- 重置密码:在重置密码时,存在多种逻辑漏洞,比如利用session覆盖重置密码、短信验证码直接在返回的数据包中等。
- 竞争条件:竞争条件常见于多种攻击场景中,比如前面介绍的文件上传漏洞。还有一个常见场景就是购物时,例如用户A的余额为10元,商品B的价格为6元,商品C的价格为5元,如果用户A分别购买商品B和商品C,那余额肯定是不够的。但是如果用户A利用竞争条件,使用多线程同时发送购买商品B和商品C的请求,可能会出现以下这几种结果。
越权访问攻击
页面实现的功能是,当用户登录系统后,可以通过该页面查看自己的密码,该URL中存在一个参数username=zhangsan,当我们把参数username改为lisi之后,则可看到用户lisi的信息。
数据库是这样滴:
越权访问代码分析
服务端处理用户查询个人信息的代码如下,程序设计的思路如下所示
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>个人信息</title>
</head>
<body>
<?php
$con=mysqli_connect("localhost","root","qwer","test");
if (mysqli_connect_errno())
{
echo "连接失败: " . mysqli_connect_error();
}
if (isset($_GET['username'])) {
$result = mysqli_query($con,"select * from users where `username`='".addslashes($_GET['username'])."'");
$row = mysqli_fetch_array($result,MYSQLI_ASSOC);
exit(
'用 户:<input type="text" name="username" value="'.$row['username'].'" > <br />'.
'密 码:<input type="password" value="'.$row['password'].'" > <br />'.
'邮 箱:<input type="text" value="'.$row['email'].'" > <br />'.
'地 址:<input type="text" value="'.$row['address'].'" > <br />'
);
}else{
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysqli_query($con,"select * from users where `username`='".addslashes($username)."' and `password` = '".($password)."'");
$row = mysqli_fetch_array($result);
if ($row) {
exit("登录成功"."<a href='login.php?username=".$username."' >个人信息</a>");
}else{
exit("登录失败");
}
}
?>
</body>
</html>
- 在else语句中获取POST的参数username和参数password,然后到数据库中查询,如果正确,则登录成功,然后跳转到login.php?username=$username处(if语句)。
- if语句中是登录成功后的代码,获取GET的参数username,然后到数据库中查询参数username的所有信息,并返回到页面上。但是此处没有考虑的是,如果直接访问login.php?username=admin, 那么将直接执行if语句中的代码,而没有执行else语句中的代码,所以此处不需要登录就可以查看admin的信息,通过这种方式,就可以越权访问其他用户的信息。
修复建议
越权访问漏洞产生的主要原因是没有对用户的身份做判断和控制,防护这种漏洞时,可以通过session来控制。例如在用户登录成功后,将username或uid写入到session中,当用户查看个人信息时,从session中取出username, 而不是从GET或POST取username,那么此时取到的username就是没有被篡改的。