技术笔记

参数化查询如何解决掉了SQL注入

字号+ 作者:sn0w 来源:转载 2016-11-27 14:53 我要评论( )

先看一段存在sql注入的代码: [PHP] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ......

先看一段存在sql注入的代码:
[PHP] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
  //数据库连接
  $mysqli=new mysqli('localhost','root','root','test');
  if ($mysqli->connect_errno) {
    die('ERROR:'.$mysqli->connect_errer);
  }
  //数据库查询操作
  if (!empty($_POST['sub'])) {
    //获取参数
    $user=$_POST['username'];
    $pass=md5($_POST['password']);
    //构造语句
    $sql="SELECT * FROM mysqli_test WHERE username='{$user}' AND password='{$pass}'";
    echo $sql;
    //执行语句
    $result=$mysqli->query($sql);
    //验证登录
    if($result && $result->num_rows>0){
      echo "<br /> OK";
    }else {
      echo "NO";
    }
 
  }
 ?>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Login </title>
  </head>
  <body>
    <form action="prepare.php" method="post">
      username:<input type="text" name="username" value=""><br/>
      password:<input type="password" name="password" value=""><br/>
      <input type="submit" name="sub" value="Login">
 
    </form>
  </body>
</html>

参数没有进行任何过滤 而且查询后没有对数据进行验证,看到这我们应该想到万能密码(万能密码的原理
正常的查询如图

我们用万能密码尝试登录,我们可以看到红线之后的所有数据已经被注释掉,只有之前的语句被mysql所执行,同时后边的and 1=1返回永远为1,从而造成万能密码

下面看一下我们修改为预置参数查询后的代码:

[PHP] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
  //数据库连接
  $mysqli=new mysqli('localhost','root','root','test');
  if ($mysqli->connect_errno) {
    die('ERROR:'.$mysqli->connect_errer);
  }
  //---------------------------------------参数化查询
  if (!empty($_POST['sub'])) {
      //获取参数
      $user=$_POST['username'];
      $pass=md5($_POST['password']);
      //构造语句
      $sql="SELECT * FROM mysqli_test WHERE username=? AND password=?";
      //准备执行sql语句
      $mysqli_stmt=$mysqli->prepare($sql);
      //传递参数
      $mysqli_stmt->bind_param('ss',$user,$pass);
      //执行语句 验证登录
      if ($mysqli_stmt->execute()) {
        //获取结果集 返回行数
        $mysqli_stmt->store_result();
        //验证登录
        if ($mysqli_stmt->num_rows>0) {
          echo "OK";
        }else {
          echo "NO";
        }
      }else {
          //  打印错误
          echo $mysqli_stmt->error;
      }
  }
 
 ?>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Login </title>
  </head>
  <body>
    <form action="prepare.php" method="post">
      username:<input type="text" name="username" value=""><br/>
      password:<input type="password" name="password" value=""><br/>
      <input type="submit" name="sub" value="Login">
 
    </form>
  </body>
</html>

我们正常登录  

我们看一下执行的语句(mysql日志)

我们再试一下万能密码  发现登录并没有成功

我们再看一下执行的语句

我们将将16进制转换一下


--------
我们将参数化查询与普通的查询对比一下

可以看到 参数化查询在真正执行之前会进行数据库预编译 放在缓存里面,当运行时动态地参数传递,即使参数里有敏感字符 数据库也会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令。

本文来自: 蜗蜗侠's Blog-关注网络安全 http://blog.icxun.cn/Note/321.html

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 转大表哥安全狗SQL注入语句(176处)

    转大表哥安全狗SQL注入语句(176处)

    2017-12-05 13:47

  • Mysql注入点在limit关键字后面的利用方法

    Mysql注入点在limit关键字后面的利用方法

    2016-12-18 15:06

  • 一个罕见的MSSQL注入漏洞案例

    一个罕见的MSSQL注入漏洞案例

    2016-12-18 15:03

  • postgresql注入之文件读写

    postgresql注入之文件读写

    2016-12-13 15:25

网友点评
暂时未开启评论功能~