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

(0)

相关推荐

  • php插入中文到sqlserver 2008里出现乱码的解决办法分享

    今天使用php操作数据库时发现插入SQL Server 2008数据库里的中文字段出现乱码,下面是我一开始时的一些情况: 开发环境是php5.3.3+Apache2.2.17+SQL Server 2008,php脚本文件的编码是utf-8,传给数据库的编码是GB2312(SQL Server的默认字符编码可能是这个,我不肯定),我用的是微软官方提供的SQLSRV库来连接数据库的(PS:SQL Server 2005开始已经不支持用mssql.dll来连接了),故使用sqlsrv_query($

  • PHP连接SQLSERVER 注意事项(附dll文件下载)

    环境: - Apache 2.2.6 - PHP 5.2.5 - SQL Server 2005 - Windows XP SP2 步骤: 1. 首先按通常做法配置好PHP5连接MS SQL Server 2. 下载正确版本的 ntwdblib.dll (2000.80.194.0),注意这个版本号,不是这个版本的dll 不起作用啊,刚开始搞了好久才发现这个问题,切记... 地址: http://www.jb51.net/dll/ntwdblib.dll.html 3. 覆盖 apache2.2

  • PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】

    本文实例讲述了PHP基于PDO调用sqlserver存储过程的方法.分享给大家供大家参考,具体如下: 由于业务这边存储过程一直在sqlserver上面,所以要用php去调用它,然而我们本地的是windows,而线上又是linux,一开始使用Yii框架的一些机制去调用发现在本地一直都是好的然而到线上就不行了,找了很多方案,最后找到了pdo这种方案,而本地使用的驱动是sqlsrv线上是dblib所以需要注意下链接pdo时的驱动形式,在取结果集的时候注意windows和linux好像有所不同,在我加上

  • Win2003+apache+PHP+SqlServer2008 配置生产环境

    安装前的准备: 1.Apache2.2.2 2.PHP5.2.17 3.SqlServer2008 4.sqlncli.msi(SqlServer客户端,可以到微软官方网站去下载) 5.ntwdblib.dll (2000.80.194.0) 6.SQLSRV20.exe,即MicrosoftDriver 2.0 for PHP for SQL Server(sql server 2005 及2008使用SQLSRV20.exe, SQL Server 2010使用SQLSRV30.exe)(需

  • Linux下php连接SQLServer 2000数据库的配置方法

    说明: Linux服务器系统:CentOS 5.5 Web环境:LAMP或者LNMP Windows服务器系统:Windows Server 2003 Windows服务器IP地址:192.168.21.134 数据库环境:SQL Server 2000数据库 数据库账号:sa 数据库密码:123456 实现目的:Linux服务器中的php程序能够连接到Windows服务器中的SQL Server 2000数据库 具体步骤: 一.在Linux服务器中安装freetds 1.安装编译工具及驱动程序

  • PHP连接SQLServer2005的实现方法(附ntwdblib.dll下载)

    php连接sql2005的问题,现在整合,同时把FAQ整合上. 我前面写的教程: 连接前配置系统: 1.检查文件 php5.2.5/ntwdblib.dll 默认下面有一个,不能连接再替换. 下载正确版本的 ntwdblib.dll (2000.80.194.0),地址: http://www.jb51.net/dll/ntwdblib.dll.html 2.配置php a.打开php.in将extension=php_mssql.dll的注释符号去掉. b.打开php.in将mssql.sec

  • PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】

    本文实例讲述了PHP基于pdo的数据库操作类.分享给大家供大家参考,具体如下: 工作中需要操作sqlserver.oracle都是使用的这个类,当时是在别人的基础上改进了,现在分享下 <?php class Pdodb{ protected $pdo; protected $res; protected $config; /*构造函数*/ function __construct($config){ $this->Config = $config; $this->connect(); }

  • php使用pdo连接sqlserver示例分享

    下载PDO_DBLIB库 PDO的各种库都可以在PECL中找到,例如,MySQL库:PDO_MYSQL.Oracle库:PDO_OCI. 作为SQL Server 的连接库,通过下面命令下载PDO_DBLIB: 复制代码 代码如下: wget http://pecl.php.net/get/PDO_DBLIB 安装PDO_DBLIB库 下载完成后通过PEAR安装: 复制代码 代码如下: /usr/bin/pear install PDO_DBLIB-1.0.tgz 如果安装成功的话,/usr/l

  • php5.3中连接sqlserver2000的两种方法(com与ODBC)

    1.Com链接,ADODB.Connection 复制代码 代码如下: $conn = new Com("ADODB.Connection"); //实例化一个Connection对象 $connstr = "provider=sqloledb;datasource=.;uid=sa;pwd=123456;database=jnold;"; $conn->Open($connstr); $rs = new Com("ADODB.Recordset&q

  • PHP6连接SQLServer2005的三部曲

    1.修改php.ini将extension=php_mssql.dll的注释删除保存. 修改php.in将mssql.secure_connection = Off改为mssql.secure_connection = On. 2.下载连接2005的ntwdblib.dll (2000.80.194.0) 点击下载 3. 打开文件X:\AppServ\php5\ext,把php_mssql.dll 复制到system32目录下. 把下载的ntwdblib.dll 复制到system32目录下.

  • PHP连接SQLServer2005方法及代码

    1.修改php.ini将extension=php_mssql.dll的注释删除保存. 修改php.in将mssql.secure_connection = Off改为mssql.secure_connection = On. 2.下载连接2005的 ntwdblib.dll (2000.80.194.0) 点击下载 3. 打开文件X:\AppServ\php5\ext ,把php_mssql.dll 复制到system32目录下. 把下载的ntwdblib.dll 复制到system32目录下

  • PHP连接SQLServer2005 的问题解决方法

    后来火了,在虚拟机装上WIN2003一试,加载MSSQL模块是没问题了,但是用mssql_connect("localhost", "sa", "");却怎么也连不上数据库,后来上网查了很多资料,才终于搞定了: 环境:IIS6.0+PHP5+SQL Server2005 SQL Server安装的时候选择混合登陆模式,即windows和sql server身份验证模式. 步骤: 1. 首先按通常做法配置好PHP5连接MS SQL Server P

  • PHP连接SQLServer2005的方法

    1.修改php.ini将extension=php_mssql.dll的注释删除保存. 修改php.in将mssql.secure_connection = Off改为mssql.secure_connection = On. 2.下载连接2005的ntwdblib.dll (2000.80.194.0) 点击下载 3. 打开文件X:\AppServ\php5\ext,把php_mssql.dll 复制到system32目录下. 把下载的ntwdblib.dll 复制到system32目录下.

随机推荐