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

 更新时间:2021年09月02日 12:17:45   作者:Zeker62  
这篇文章主要介绍了万能密码的SQL注入漏洞其PHP环境搭建及防御手段,对此感兴趣的小伙伴赶快收藏起来吧

万能密码的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 数据库备份和还原认识和总结 (一)

    SQL Server 数据库备份和还原认识和总结 (一)

    可能许多同学对SQL Server的备份和还原有一些了解,也可能经常使用备份和还原功能,我相信除DBA之外我们大部分开发员队伍对备份和还原只使用最基础的功能,对它也只有一个大概的认识,如果对它有更深入的认识,了解它更全面的功能岂不是更好,到用时会得心应手
    2012-08-08
  • 分页 SQLServer存储过程

    分页 SQLServer存储过程

    分页 SQLServer存储过程...
    2006-08-08
  • SQL Server利用bcp命令把SQL语句结果生成文本文件

    SQL Server利用bcp命令把SQL语句结果生成文本文件

    在SQL Server里可以调用DOS下的命令行工具bcp来实现把表里的数据或者SQL语句结果生成文本文件,详细看下操作方法,感兴趣的你可不要错过了哈
    2013-02-02
  • 大型项目中Java连接MSSQL的性能优化

    大型项目中Java连接MSSQL的性能优化

    在大型项目中,Java语言和MSSQL数据库的结合应用变得越来越流行,这不但是因为Java语言提供高度可移植性和高效处理大量数据的优势,而且MSSQL具备高效便捷的存储和数据查询能力,今天我们将讨论如何在Java项目中与MSSQL数据库进行交互
    2024-02-02
  • SQL Server 2000“设备激活错误”的解决方法

    SQL Server 2000“设备激活错误”的解决方法

    数据库恢复时出现诸如“设备激活错误,请使用with move选项来标志该文件的有效位置”报错的解决方法
    2013-11-11
  • 使用SQL语句实现查询排序,顺序和倒序

    使用SQL语句实现查询排序,顺序和倒序

    这篇文章主要介绍了使用SQL语句实现查询排序、顺序和倒序,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • SQL Server数据类型char、nchar、varchar、nvarchar的区别浅析

    SQL Server数据类型char、nchar、varchar、nvarchar的区别浅析

    这篇文章主要介绍了SQL Server数据类型char、nchar、varchar、nvarchar的区别浅析,本文写的比较容易明白,需要的朋友可以参考下
    2014-06-06
  • SQL Server的彻底卸载与再次安装方式

    SQL Server的彻底卸载与再次安装方式

    这篇文章主要介绍了SQL Server的彻底卸载与再次安装方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • sqlserver连接错误之SQL评估期已过的问题解决

    sqlserver连接错误之SQL评估期已过的问题解决

    很久没用sqlserver了,现在出现评估期已过的问题,本文就介绍一下sqlserver连接错误之SQL评估期已过的问题解决,文中根据图文详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • SQL中的分组查询与联合查询举例详解

    SQL中的分组查询与联合查询举例详解

    这篇文章主要介绍了GROUPBY分组查询和联合查询在数据库操作中的应用,GROUPBY用于将数据分组并进行聚合计算,而联合查询则通过连接多个表或子查询的结果来获取更复杂的数据集,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-02-02

最新评论