• sql注入代码分析及预防


    sql注入的原因,表面上说是因为 拼接字符串,构成sql语句,没有使用 sql语句预编译,绑定变量。但是更深层次的原因是,将用户输入的字符串,当成了 “sql语句” 来执行。

    1.union注入攻击

    <?php
    $con=mysqli_connect("localhost","root","","test");
    // 检测连接
    if (mysqli_connect_errno())
    {
        echo "连接失败: " . mysqli_connect_error();
    }

    $id = $_GET['id'];

    $result = mysqli_query($con,"select * from users where `id`=".$id);

    while($row = mysqli_fetch_array($result))
    {
        echo $row['username'] . " " . $row['address'];
        echo "<br>";
    }
    ?>

    当前端通过get方法传参进来之后,如果没有进行判断,或者过滤一些非法的字符串,这些非法的字符串,就会和$result = mysqli_query($con,"select * from users where `id`=".$id);拼接在一起,然后传入后台数据库,进行sql语句查询,然后数据库会返回来所查询到的信息,以至于泄露用户的账号及其密码等敏感信息,因此程序员在编写程序时,一定要对传入的参数值进行过滤。

    2.boolean注入攻击

    <?php
    $con=mysqli_connect("localhost","root","","test");
    // 检测连接
    if (mysqli_connect_errno())
    {
        echo "连接失败: " . mysqli_connect_error();
    }

    $id = $_GET['id'];

    if (preg_match("/union|sleep|benchmark/i", $id)) {
        exit("no");
    }

    $result = mysqli_query($con,"select * from users where `id`='".$id."'");

    $row = mysqli_fetch_array($result);

    if ($row) {
        exit("yes");
    }else{
        exit("no");
    }


    ?>

    3.报错注入

    <?php
    $con=mysqli_connect("localhost","root","","test");
    // 检测连接
    if (mysqli_connect_errno())
    {
        echo "连接失败: " . mysqli_connect_error();
    }

    $username = $_GET['username'];

    if($result = mysqli_query($con,"select * from users where `username`='".$username."'")){
        echo "ok";
    }else{
        echo mysqli_error($con);      /*这个语句本不应该在这里出现的,在编写程序时,程序员为了检查代码,然后造成了报错sql注入,如果将输出语句改成 echo "no",即便查询语句传入数据库,但也没办法在前端              显示,但是还是要对传入的参数进行过滤的*/
    }

    ?>

    通过上面两个实例,我们对sql注入有了初步的了解,平时应该怎样防御sql注入呢?

    4.sql注入的防御

    1>采用sql语句预编译和绑定变量,是防御sql注入的最佳方法。

    String  sql = "select  * from test where id=?";

    PreparedStatement  ps = conn.prepareStatement(sql);

    ps.setInt(1,id);

    ps.executeQuery();

    通过采用PreparedStatement,就会将sql语法 "select  * from test where id=?" 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响sql语句的语法结构,因为语法分析已经完成了,而语法分析主要是分析sql命令,如select,from,等等,所以即便你后面输入了这些sql命令,也不会当成sql命令来执行,因为这些sql命令的执行,必须先得通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql命令来执行的,只会被当做字符串字面值参数。所以sql语句预编译可以防御sql注入

    2>除了以上得方法,我们还需要使用一些安全函数来防止sql注入,因为不是所有场景都能够采用 sql语句预编译,有一些场景必须的采用 字符串拼接的方式。

    比如 String sql = "select * from test where id =" +id;

    在接收到用户输入的参数时,我们就严格检查 id,只能是int型。复杂情况可以使用正则表达式来判断。这样也是可以防止sql注入的。

    MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
    name = ESAPI.encoder().encodeForSQL(codec, name);
    String sql = "select * from test where name=" + name;
    ESAPI.encoder().encodeForSQL(codec, name)
    该函数会将 name 中包含的一些特殊字符进行编码,这样 sql 引擎就不会将name中的字符串当成sql命令来进行语法分析了。
  • 相关阅读:
    面试必备的数据库悲观锁与乐观锁
    5分钟带你读懂事务隔离性与隔离级别
    带你了解数据库中事务的ACID特性
    带你了解数据库中group by的用法
    带你了解数据库中JOIN的用法
    一篇带你读懂TCP之“滑动窗口”协议
    通过“表白”的方式,让我们快速了解网络协议
    聊一聊Iterable与Iterator的那些事!
    一篇让你明白进程与线程之间的区别与联系
    MySQL 索引的增删查
  • 原文地址:https://www.cnblogs.com/lzkalislw/p/15477780.html
Copyright © 2020-2023  润新知