gpt4 book ai didi

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

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 28 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章万能密码的SQL注入漏洞其PHP环境搭建及防御手段由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

1、环境搭建

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

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

2、session会话

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

3、环境搭建代码

1、创建数据库脚本

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<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代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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代码:

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

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

?
1
2
3
4
5
6
<?php
session_start();
session_unset();
session_destroy();
echo "注销成功" ;
?>

6、登录成功欢迎界面

?
1
2
3
4
5
6
7
8
9
10
<?php
session_start();
if(isset($_SESSION[ 'username' ])){
     echo "欢迎用户" .$_SESSION[ 'username' ]. "登录" ;
     echo "<br>" ;
     echo "<a href=logout.php>退出登录</a>" ;
} else {
     echo "您没有权限访问" ;
}
?>

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

4、万能密码漏洞剖析

  • 用户名输入' 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'

5、万能密码攻击防护

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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
?
1
2
$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前面加上一个字符形成一个复杂的汉字,那么单引号仍然会被输出 。

6、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 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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环境搭建 防御手段的资料请关注我其它相关文章! 。

原文链接:https://www.cnblogs.com/Zeker62/p/15216324.html 。

最后此篇关于万能密码的SQL注入漏洞其PHP环境搭建及防御手段的文章就讲到这里了,如果你想了解更多关于万能密码的SQL注入漏洞其PHP环境搭建及防御手段的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com