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


Posted in SQL Server onSeptember 04, 2021

万能密码的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环境搭建 防御手段的资料请关注三水点靠木其它相关文章!

SQL Server 相关文章推荐
2021-4-3课程——SQL Server查询【2】
Apr 05 SQL Server
SQL Server数据定义——模式与基本表操作
Apr 05 SQL Server
Sql-Server数据库单表查询 4.3实验课
Apr 05 SQL Server
SqlServer 垂直分表(减少程序改动)
Apr 16 SQL Server
SQL Server中交叉联接的用法详解
Apr 22 SQL Server
SqlServer数据库远程连接案例教程
Jul 15 SQL Server
Windows环境下实现批量执行Sql文件
Oct 05 SQL Server
SQL Server表分区删除详情
Oct 16 SQL Server
SQL Server数据库查询出现阻塞之性能调优
Apr 10 SQL Server
SQL Server中使用表变量和临时表
May 20 SQL Server
SQL Server使用PIVOT与unPIVOT实现行列转换
May 25 SQL Server
SQL Server删除表中的重复数据
May 25 SQL Server
sql server删除前1000行数据的方法实例
Aug 30 #SQL Server
SQLServer之常用函数总结详解
Aug 30 #SQL Server
SQL写法--行行比较
Aug 23 #SQL Server
SQL语句中JOIN的用法场景分析
sql通过日期判断年龄函数的示例代码
Jul 16 #SQL Server
利用 SQL Server 过滤索引提高查询语句的性能分析
SqlServer数据库远程连接案例教程
You might like
php curl post 时出现的问题解决
2014/01/30 PHP
php实现天干地支计算器示例
2014/03/14 PHP
ThinkPHP调用百度翻译类实现在线翻译
2014/06/26 PHP
php中 $$str 中 &quot;$$&quot; 的详解
2015/07/06 PHP
php框架CodeIgniter主从数据库配置方法分析
2018/05/25 PHP
PHP中“=&gt;
2019/03/01 PHP
PHP中命名空间的使用例子
2019/03/22 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
PHP钩子实现方法解析
2019/05/21 PHP
jquery blockUI 遮罩不能消失与不能提交的解决方法
2011/09/17 Javascript
分别用marquee和div+js实现首尾相连循环滚动效果,仅3行代码
2011/09/21 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
Javascript URI 解析介绍
2015/03/15 Javascript
JavaScript实现的简单幂函数实例
2015/04/17 Javascript
js实现每日自动换一张图片的方法
2015/05/04 Javascript
Javascript OOP之面向对象
2016/07/31 Javascript
jQuery实现的事件绑定功能基本示例
2017/10/11 jQuery
Nuxt.js实战详解
2018/01/18 Javascript
vue实现自定义日期组件功能的实例代码
2018/11/06 Javascript
JS实现获取数组中最大值或最小值功能示例
2019/03/02 Javascript
[58:59]完美世界DOTA2联赛PWL S3 access vs CPG 第一场 12.13
2020/12/16 DOTA
Python 随机生成中文验证码的实例代码
2013/03/20 Python
Python实现购物系统(示例讲解)
2017/09/13 Python
使用pandas中的DataFrame数据绘制柱状图的方法
2018/04/10 Python
简单谈谈python基本数据类型
2018/09/26 Python
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
对python中的 os.mkdir和os.mkdirs详解
2018/10/16 Python
python通过opencv实现图片裁剪原理解析
2020/01/19 Python
python中如何使用虚拟环境
2020/10/14 Python
应用心理学个人求职信范文
2013/12/11 职场文书
优秀团干部个人事迹
2014/05/29 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
防卫过当辩护词
2015/05/21 职场文书
《七月的天山》教学反思
2016/02/19 职场文书
python3.9之你应该知道的新特性详解
2021/04/29 Python
码云(gitee)通过git自动同步到阿里云服务器
2022/12/24 Servers