数据库教程:万能密码的SQL注入漏洞其PHP环境搭建及防御手段

目录万能密码的sql注入漏洞其php环境搭建及防御手段2、使用php转义函数六、mysqli 参数化查询万能密码的sql注入漏洞其php环境搭建及防御手段一、环境搭建这个渗透环境的搭建有以下几点:

目录
  • 万能密码的sql注入漏洞其php环境搭建及防御手段
    • 一、环境搭建
    • 二、session会话
    • 三、环境搭建代码
      • 1、创建数据库脚本
      • 2、登录界面html
      • 3、查询数据库是否为正确的账号密码php代码
      • 4、连接数据库php代码:
      • 5、注销登录代码(即关闭session会话)
      • 6、登录成功欢迎界面
    • 四、万能密码漏洞剖析
      • 五、万能密码攻击防护
        • 1、使用正则表达式限制用户输入
        • 2、使用php转义函数
        • 3、转义函数的弊端
      • 六、mysqli 参数化查询

      万能密码的sql注入漏洞其php环境搭建及防御手段

      一、环境搭建

      这个渗透环境的搭建有以下几点:

      • 基于session的会话
      • 登录界面
      • 登录成功界面
      • 注销界面
      • 数据库搭建
      • 数据库连接

      二、session会话

      • 服务器端利用session_start()函数发起一次session的会话
      • 此时我们登录成功后用户的数据被保存在服务器端的cookie: session= ,即sessionid
      • 如果需要再次访问
      • 服务器端的$_session['...']会获取用户session
      • 然后与原本存在于服务器的sessionid进行比对,如果比对成功,则证明用户正确

      三、环境搭建代码

      1、创建数据库脚本

      在mysql中使用source命令即可运行脚本:

        drop database if exists lab;  create database lab;  use lab;    create table users  (      id int not null auto_increment,      username char(32) not null,      passcode char(32) not null,      primary key(id)  );    insert into users(username,passcode) values('admin','admin123');  insert into users(username,passcode) values('alice','alice456');  

      2、登录界面html

        <html>    <head>      <meta charset="utf-8">      <title>login</title>      <style>          #a {              width: 500px;              text-align: center;          }                    .b {              width: 200px;              height: 30px;          }      </style>  </head>    <body>      <div id=a>          <h2>login!</h2>          <form name="form_login" method="post" action="check_login.php">              username:<input type="text" class="b" name="username" /><br> <br>     password:<input type="password" class="b" name="password" /><br>              <input type="submit" name="submit" value="submit" />              <input type="reset" name="reset" value="reset" />          </form>      </div>  </body>    </html>    

      3、查询数据库是否为正确的账号密码php代码

        <?php  include('con_database.php');    $username=isset($_post['username'])?$_post['username']:'';  $password=isset($_post['password'])?$_post['password']:'';  if($username=='' || $password==''){      echo "<script>alert('请输入账号和密码!')</script>";      exit;  }    $sql="select * from users where username='$username' and passcode='$password'";    $query=mysqli_query($con,$sql) or die('sql语句执行失败'.mysqli_error($con));  if ($row=mysqli_fetch_array($query)){      session_start();      $_session['username']=$row[1];      echo "<a href='welcome.php'>欢迎访问</a>";  }else{      echo "<script>alert('登录失败!');history.go(-1)</script>";  }  mysqli_close($con);  ?>      

      4、连接数据库php代码:

        <?php  $con=mysqli_connect('127.0.0.1','root','root') or die("数据库连接失败!");  mysqli_select_db($con,'lab')or die("数据库连接失败");  ?>

      5、注销登录代码(即关闭session会话)

        <?php  session_start();  session_unset();  session_destroy();  echo "注销成功";  ?>

      6、登录成功欢迎界面

        <?php  session_start();  if(isset($_session['username'])){      echo "欢迎用户".$_session['username']."登录";      echo "<br>";      echo "<a href=logout.php>退出登录</a>";  }else{      echo "您没有权限访问";  }  ?>      

      至此,我们的渗透环境就构建好了

      四、万能密码漏洞剖析

      • 用户名输入' or 1=1 or',密码随意,发现可以登录进去
      • 密码输入 'or '1=1 也可以登录进去

      当然登录方法不止一种:

      原来查询语句是这样的:

      $sql="select * from users where username='$username' and passcode='$password'";

      经过注入之后,变成:

      $sql="select * from users where username='' or 1=1 or ' and passcode='****'";

      我们观察到,where后面呃字句中的username被闭合,并且字句分成三个句子并用or连接。
      在sql语句中 and的优先级要大于or,所以1=1先判断,为真,即where后面的语句为真,即整个sql语句为真,即表示查询正确
      而形成的语句可以将整个users表查询,后面的$row=mysqli_fetch_array($query)选择的是查询的第一行值,这样满足了sql语句并跳过了登录验证
      由此可以引申出,只要where后面字句为真,即可跳过验证,有如下衍生方法:

      • ' or 1=1 #
      • ' or 1=1 -- (后面有空格)
      • 'or"="or'

      五、万能密码攻击防护

      1、使用正则表达式限制用户输入

      可以使用正则表达式限制用户的用户名输入,比如:/^[a-z0-9a-z_]{5,16}$/
      这个限制了用户5位以上16位以下的字母数字下划线为用户名的输入
      这个限制在check_login.php中添加

        <?php  include('con_database.php');    $username=isset($_post['username'])?$_post['username']:'';  $password=isset($_post['password'])?$_post['password']:'';  if (!preg_match("/^[a-z0-9a-z_]{5,16}$/",$username)){      echo "<script>alert('用户名格式错误')</script>";      exit;    if($username=='' || $password==''){      echo "<script>alert('请输入账号和密码!')</script>";      exit;  }    $sql="select * from users where username='$username' and passcode='$password'";    $query=mysqli_query($con,$sql) or die('sql语句执行失败'.mysqli_error($con));  if ($row=mysqli_fetch_array($query)){      session_start();      $_session['username']=$row[1];      echo "<a href='welcome.php'>欢迎访问</a>";  }else{      echo "<script>alert('登录失败!');history.go(-1)</script>";  }  mysqli_close($con);  }  ?>  

      2、使用php转义函数

      • addslashes()函数:能够将单引号、双引号、反斜杠和null转义
      • mysql_escape_string()函数、mysql_real_escape_string()函数这个是转义sql语句中的符号,php7.x版本的都要变成mysqli
        $username=isset($_post['username'])?addslashes($_post['username']):'';  $password=isset($_post['password'])?mysqli_real_escape_string($con,$_post['password']):'';    

      3、转义函数的弊端

      因为使用的是utf-8编码,不是宽字节编码,形成的’会被变成%5c%27
      windows下默认的是宽字节的gbk编码
      如果在%5c前面加上一个字符形成一个复杂的汉字,那么单引号仍然会被输出

      六、mysqli 参数化查询

      在使用参数化查询的情况下,服务器不会将参数的内容是为sql指令中的一部分
      而是在数据库完成sql指令的编译之后,再代入参数运行
      此时就算参数里面有恶意数据
      但是此时sql语句以及编译完成
      就不会被数据库运行

      php提供了三种访问mysql数据库的拓展:

      • mysql (php5.5起,已经废除)
      • mysqli
      • pdo(php data object php数据对象)

      pdo和mysqli提供面向对象的api
      mysqli也存在面向过程的api,所以容易从mysql转换到mysqli

      下面是mysqli形式的check_login.php 写法,新建check_login_mysqli.php

        <?php  include('con_database.php');    $username=isset($_post['username'])?$_post['username']:'';  $password=isset($_post['password'])?$_post['password']:'';    if($username==''||$password==''){      echo "<script>alert('错误!');history.go(-1);</script>";      exit;  }  $sql="select * from users where username=? and passcode=? ;";//问号表示需要一个参数  $stmt=$con->prepare($sql);//预编译sql语句  if(!$stmt){      echo 'prepare 执行错误';  }  else{      $stmt->bind_param("ss",$username,$password); //为预编译绑定sql参数,ss表示两个字符串      //i——int d——double  s——string   b——boolean      $stmt->execute();      $result=$stmt->get_result();      $row=$result->fetch_row();      if($row){          session_start();          $_session['username']=$row[1];          echo $row[1]."<a href='welcome.php'>欢迎访问</a>";      }else{          echo "<script>alert('登录失败!!');history.go(-1);</script>";      }      $stmt->close();  }  $con->close();  ?>    

      一些内容已经标记在代码的注释里面
      参数化的php代码真的能够很有效地防止sql注入。

      以上就是万能密码的sql注入漏洞其php环境搭建及防御手段的详细内容,更多关于万能密码的sql注入 php环境搭建 防御手段的资料请关注<计算机技术网(www.ctvol.com)!!>其它相关文章!

      需要了解更多数据库技术:万能密码的SQL注入漏洞其PHP环境搭建及防御手段,都可以关注数据库技术分享栏目—计算机技术网(www.ctvol.com)!

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/dtteaching/888622.html

      Like (0)
      Previous 2021年10月26日
      Next 2021年10月26日

      精彩推荐