什么是越权漏洞?
越权漏洞指的是应用在检查授权时存在纰漏,可以让攻击者获得低权限用户账户后,利用一些方式绕过权限检查,可以访问或者操作其他用户或者更高权限,而越权漏洞是属于业务性漏洞,困难在于这类漏洞并不是代码本身存在问题,我们利用一些自动化检测工具很难检测出漏洞,所以我们需要额外关注这类漏洞。
越权漏洞的分类:
- 水平越权:用户在同级别用户进行越权访问,删除,修改数据
- 垂直越权:用户可以向更高级别的用户越权进行访问,修改,删除数据
- 未授权访问:攻击者在没有获得访问权的情况下可以直接进行访问,修改删除数据
简单的案例演示
-
水平越权(pikachu)
先用kobe这个用户登录,抓包
将uesrname=kobe该为username=lucy
查看源代码
登录页面 ,如果输入的用户名和密码不为空,且能在数据库中存在,就将用户名和密码存放在session中,并跳转到信息查看页面
if(isset($_POST['submit'])){
if($_POST['username']!=null && $_POST['password']!=null){
$username=escape($link, $_POST['username']);
$password=escape($link, $_POST['password']);//转义,防注入
$query="select * from member where username='$username' and pw=md5('$password')";
$result=execute($link, $query);
if(mysqli_num_rows($result)==1){
$data=mysqli_fetch_assoc($result);
$_SESSION['op']['username']=$username;
$_SESSION['op']['password']=sha1(md5($password));
header("location:op1_mem.php");
}else{
$html.="<p>登录失败,请重新登录</p>";
}
}
信息查看页面,检查session中的username值是否存在,若存在就从数据库中检索信息并打印出来。但是这里get传进去的值可以被攻击者篡改,从而造成越权漏洞,正确的方法应该是使用$_SESSION['op']['username']来进行校验,因为session存放在服务端,攻击者不能进行伪造
if(!check_op_login($link)){
header("location:op1_login.php");
}
$html='';
if(isset($_GET['submit']) && $_GET['username']!=null){
//没有使用session来校验,而是使用的传进来的值,权限校验出现问题,这里应该跟登录态关系进行绑定
$username=escape($link, $_GET['username']);
$query="select * from member where username='$username'";
$result=execute($link, $query);
if(mysqli_num_rows($result)==1){
$data=mysqli_fetch_assoc($result);
$uname=$data['username'];
$sex=$data['sex'];
$phonenum=$data['phonenum'];
$add=$data['address'];
$email=$data['email'];
<form class="msg1" method="get">
<input type="hidden" name="username" value="<?php echo $_SESSION['op']['username']; ?>" />
<input type="submit" name="submit" value="点击查看个人信息" />
</form>
垂直越权(pikachu)
先登录admin管理员账号,然后添加数据,抓取管理员账号的cookie
退出管理员账号,登录普通用户的账号,抓取cookie,将普通用户的cookie替换掉管理员账号的cookie,重新发包,数据添加成功。
代码分析:
这里check_op2_login($link) 只检测了用户的登录状态,即只检测了session是否存在,session存在就通过验证,没有进行级别验证。可以将用户权限放入session中(登录页面中,管理员用户等级为1,普通用户等级为2),然后在数据添加文件代码中添加对用户权限等级的验证。
function check_op2_login($link){
if(isset($_SESSION['op2']['username']) && isset($_SESSION['op2']['password'])){
$query="select * from users where username='{$_SESSION['op2']['username']}' and sha1(password)='{$_SESSION['op2']['password']}'";
$result=execute($link,$query);
if(mysqli_num_rows($result)==1){
return true;
}else{
return false;
}
}else{
return false;
}
}
if(!check_op2_login($link)){
header("location:op2_login.php");
exit();
}
if(isset($_POST['submit'])){
if($_POST['username']!=null && $_POST['password']!=null){//用户名密码必填
$getdata=escape($link, $_POST);//转义
$query="insert into member(username,pw,sex,phonenum,email,address) values('{$getdata['username']}',md5('{$getdata['password']}'),'{$getdata['sex']}','{$getdata['phonenum']}','{$getdata['email']}','{$getdata['address']}')";
$result=execute($link, $query);
if(mysqli_affected_rows($link)==1){//判断是否插入
header("location:op2_admin.php");
}else {
$html.="<p>修改失败,请检查下数据库是不是还是活着的</p>";
}
}
}