05-SQL注入-验证码防护

一、session验证码存在的漏洞

当验证码保存在session变量中,每一次刷新登录页面,会重新访问一次vcode.php,但是如果不刷新页面,

而是直接通过python、fiddle、burp等直接发送登录请求,则此时验证码在session中保持最后一个,

从而只需要在发送登录请求的时候将验证码设置为最后一个即可。

所有,验证码每使用一次必须清空,不允许继续给下一次使用

二、session验证防护

验证码只允许使用一次,每用一次,就需要清空,让用户不得不再次请求vcode.php,获取新的验证码

 if(strtoupper($_SESSION['vcode']) != strtoupper($vcode)){
        die("vcode-error");
    }
    else{
        // 验证码输入成功后,再清空本次session中的验证码
        unset($_SESSION['vcode']);
        // $_SESSION['vcode']='';  不能直接设置为空字符串,否则也可以在请求上提交一个空验证码,实现绕过
    }

三、避免使用cookie的验证码

session的生成过程,当用户第一次访问服务器时,如果请求中没有带Cookie字段,

则服务器会在首次调用session_start()的页面中响应一个Session ID,默认命名为:PHPSESSID,响应字段值如下:

set-cookie: //也可以理解为系统自动生成的

接下来,后续的每一个请求,将会在请求头的cookie字段中添加session ID,目的是主动告诉服务器,我是谁。

cookie: PHPSESSID=

另外,在服务器端也可以直接

验证码漏洞的防护

<?php

    include "common.php";

    // 获取用户提交的登录请求的数据
    // 使用addslashes函数对用户名进行转义
    $username = $_POST['username'];
    $password = $_POST['password'];
    $vcode = $_POST['vcode'];

    // 验证码的验证

    // 此处启用了万能验证码的漏洞==》存在安全漏洞:认证和授权失败
    // if($vcode !== '0000'){
    //     die("vcode-error");
    // }

    // 根据图片验证码进行验证
    if(strtoupper($_SESSION['vcode']) != strtoupper($vcode)){
        die("vcode-error");
    }
    else{
        // 验证码输入成功后,再清空本次session中的验证码
        unset($_SESSION['vcode']);
        // $_SESSION['vcode']='';  不能直接设置为空字符串,否则也可以在请求上提交一个空验证码,实现绕过
    }

    // 无论验证码是否正确,再提交一次请求均清空一次,但是会增加服务器的负担
    unset($_SESSION['vcode']);

    // if(strtoupper($_COOKIE['vcode']) !=strtoupper($vcode)){
    //     die("vcode-error");
    // }


    $conn=create_connection_oop();
    // create_connection_oop()

    // create_connection()是调用common.php中定义的函数,就是数据库连接的
    // $conn = create_connection();
    $sql= "select userid,username,password,role from user where username=?";
    

    // 基于面向对象和MySQL预处理功能是实现MySQL注入
    $stmt = $conn->prepare($sql);
    echo ($sql);
    $stmt->bind_param("s",$username);    // 绑定结果集
    $stmt->bind_result($userid,$username2,$passwrod2,$role);  //绑定结果参数
    $stmt->execute();
    $stmt->store_result();  //获取行数
    //$result = mysqli_query($conn,$sql) or die("SQL语句执行错误");  // $result获取到的查询结果,称为结果集

    // 以下代码没有进行爆破的防护,违背了owasp认证和授权失败
    // 获取到的行数是否为一
    if($stmt->num_rows == 1 ){
        $stmt->fetch();
        if($password == $passwrod2){
            echo "login-pass";
            // 失效的访问控制
            // url绕过

            // 登录成功后,记录session变量
            $_SESSION['username'] = $username;
            $_SESSION['islogin'] = 'true';
            echo " <script>location.href='welcome.php'</script> "; 
        }
        else{
            echo "login-fail";
            echo " <script>location.href='login.html'</script> ";

        }
         
    }
    else{
        echo "login-fail";
        echo " <script>location.href='login.html'</script> ";
    }
    // 关闭数据库
    mysqli_close($conn);
?>
// 基于面向对象和MySQL预处理功能是实现MySQL注入
    $stmt = $conn->prepare($sql);
    echo ($sql);
    $stmt->bind_param("s",$username);    // 绑定结果集
    $stmt->bind_result($userid,$username2,$passwrod2,$role);  //绑定结果参数
    $stmt->execute();
    $stmt->store_result();  //获取行数
    //$result = mysqli_query($conn,$sql) or die("SQL语句执行错误");  // $result获取到的查询结果,称为结果集
    
    

对基于面向对象的代码进行解析

这段代码是一个PHP代码片段,用于执行数据库查询并获取结果集的行数。具体来说,它执行以下操作:

  1. $conn->prepare($sql)

:这行代码使用数据库连接对象 $conn 的 prepare() 方法来准备一个 SQL 查询语句。$sql 是包含 SQL 查询语句的字符串变量。

  1. echo ($sql)

:这行代码将 SQL 查询语句的内容输出到屏幕上,以便调试和验证查询语句是否正确。

  1. $stmt->bind_param("s", $username)

:这行代码使用准备好的语句对象 $stmt 的 bind_param() 方法,将变量 $username 绑定到查询语句中的参数占位符。这里使用的是字符串类型的参数占位符 "s"。

  1. $stmt->bind_result($userid, $username2, $password2, $role)

:这行代码使用 bind_result() 方法将查询结果的列与变量进行绑定。这里将查询结果的列分别绑定到 $userid、$username2、$password2 和 $role 这些变量上。

  1. $stmt->execute()

:这行代码执行准备好的查询语句。

  1. $stmt->store_result()

:这行代码将查询结果存储在客户端的内存中,以便后续可以获取结果集的行数。

总之,这段代码的目的是准备并执行一个数据库查询语句,并将查询结果的行数存储在客户端的内存中,以便后续使用。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值