zoukankan      html  css  js  c++  java
  • 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命令来进行语法分析了。
  • 相关阅读:
    LeetCode 515. 在每个树行中找最大值(Find Largest Value in Each Tree Row)
    LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)
    LeetCode 199. 二叉树的右视图(Binary Tree Right Side View)
    LeetCode 1022. 从根到叶的二进制数之和(Sum of Root To Leaf Binary Numbers)
    LeetCode 897. 递增顺序查找树(Increasing Order Search Tree)
    LeetCode 617. 合并二叉树(Merge Two Binary Trees)
    LeetCode 206. 反转链表(Reverse Linked List) 16
    LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)
    LeetCode 110. 平衡二叉树(Balanced Binary Tree) 15
    LeetCode 108. 将有序数组转换为二叉搜索树(Convert Sorted Array to Binary Search Tree) 14
  • 原文地址:https://www.cnblogs.com/lzkalislw/p/15477780.html
Copyright © 2011-2022 走看看