万能密码的SQL注入漏洞其PHP环境搭建及代码详解+防御手段
环境搭建
这个渗透环境的搭建有以下几点
- 基于session的会话
- 登录界面
- 登录成功界面
- 注销界面
- 数据库搭建
- 数据库连接
session会话
- 服务器端利用session_start()函数发起一次session的会话
- 此时我们登录成功后用户的数据被保存在服务器端的Cookie: session= ,即sessionID
- 如果需要再次访问
- 服务器端的
$_SESSION['...']
会获取用户session - 然后与原本存在于服务器的sessionID进行比对,如果比对成功,则证明用户正确
环境搭建代码
创建数据库脚本
在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');
登录界面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>
查询数据库是否为正确的账号密码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);
?>
连接数据库php代码:
<?php
$con=mysqli_connect('127.0.0.1','root','root') or die("数据库连接失败!");
mysqli_select_db($con,'lab')or die("数据库连接失败");
?>
注销登录代码(即关闭session会话)
<?php
session_start();
session_unset();
session_destroy();
echo "注销成功";
?>
登录成功欢迎界面:
<?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'
万能密码攻击防护
使用正则表达式限制用户输入:
可以使用正则表达式限制用户的用户名输入,比如:/^[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);
}
?>
使用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']):'';
转义函数的弊端
因为使用的是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环境搭建及代码详解+防御手段的更多相关文章
- 从c#角度看万能密码SQL注入漏洞
以前学习渗透时,虽然也玩过万能密码SQL注入漏洞登陆网站后台,但仅仅会用,并不理解其原理. 今天学习c#数据库这一块,正好学到了这方面的知识,才明白原来是怎么回事. 众所周知的万能密码SQL注入漏洞, ...
- 利用SQL注入漏洞登录后台的实现方法
利用SQL注入漏洞登录后台的实现方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-01-12我要评论 工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读 ...
- 利用SQL注入漏洞登录后台的实现方法 。。。。转载
一.SQL注入的步骤 a) 寻找注入点(如:登录界面.留言板等) b) 用户自己构造SQL语句(如:' or 1=1#,后面会讲解) c) 将sql语句发送给数据库管理系统(DBMS) d) DBMS ...
- SQL 注入漏洞浅研究学习
SQL注入漏洞:Web安全方面最高危的漏洞,SQL漏洞威胁着网站后台数据的安全问题. 网上常说“万能密码”,这个万能密码则就是利用了SQL注入漏洞: ' or 1=1 -- 上述的万能密码输入在用户登 ...
- SQL注入漏洞技术的详解
SQL注入漏洞详解 目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 Up ...
- SQL注入漏洞详解
目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 UpdateXml报错注 ...
- 浅谈SQL注入漏洞以及防范策略
--HeShiwei 2014-5-15 什么是SQL注入 SQL注入,指的是用户通过向登录框输入恶意字符,利用代码的字符串拼接漏洞进行网站注入攻击,最终导致整个网站用户表信息泄露的攻击方式.黑客就是 ...
- sql注入漏洞笔记随笔
sql注入是从1998年出现的,是一个十分常见的漏洞,它是OWASP top10的第一名(注入) 在了解sql注入之前,我们需要先了解web框架 webapp:web网站,这种方式它采用的是B/S架构 ...
- PHPCMS \phpcms\modules\member\index.php 用户登陆SQL注入漏洞分析
catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述2. 漏洞触发条件 0x1: POC http://localhost/p ...
随机推荐
- 开发工具IDE从入门到爱不释手(二)开发中必会技能
一.高效的代码编辑技能 1.复制和复制历史 Ctrl+C:复制,点中你要复制的行,,完成复制 Ctrl+Shift+V:复制历史, 查看最近复制的五条历史记录 Ctrl+D:直接复制出光标所在行 Al ...
- Distance Queries 距离咨询 (LCA倍增模板)
农夫约翰有N(2<=N<=40000)个农场,标号1到N.M(2<=M<=40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地 ...
- 【开源】这可能是封装微信 API 最全的 .NET SDK 了
## 缘起 今年公司某个项目需要全面接入微信支付 V3 版 API.起初觉得,2014 年微信支付就已上线了 V3 版 API,这都 2021 年了,就算官方不给力,怎么着社区也该有几个造好的 .NE ...
- 查看filesystem type及ftype的值
查看Filesystem type df -Th 查看ftype xfs_info [filesystem_name] | grep ftype
- CSS 即将支持嵌套,SASS/LESS 等预处理器已无用武之地?
最近,有一则非常振奋人心的消息,CSS 即将原生支持嵌套 -- Agenda+ to publish FPWD of Nesting,表示 CSS 嵌套规范即将进入规范的 FWPD 阶段. 目前对应的 ...
- 网安日记④之搭建域环境(domain)并且配置域
搭建域环境(domain)并且配置域 什么是域 域就是将多台计算机在逻辑上组织到一起,进行集中管理,也就是创建在域控制器上的组,将组的账户信息保存在活动目录中.域组可以用来控制域内任何一台计算机资源的 ...
- springcloud搭建高可用注册中心的时候注册中心在unavailable-replicas中的问题
在搭建springcloud eureka高可用注册中心时,发现另一个注册中心一直在unavailable-replicas不可用分片,原因为原来为单个注册中心的时候,禁止了注册中心自主注册为服务和检 ...
- Vulnhub----bulldog靶场笔记
前提条件 kali和bulldog靶机的的ip地址在同一个网段 本测试环境: kali:192.168.56.102 bulldog:192.168.56.101 主机探测 利用kali的netdis ...
- JavaScript new 关键词解析及原生实现 new
java里面,new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,原型语言没类,只有对象与原型链继承 JavaScript 中 new 表达式的作用是生成 ...
- JAVA的一般输入输出 和 快速输入输出 (BufferedReader&BufferedWrite)(转载)
1.JAVA的一般输入输出 和 快速输入输出 (BufferedReader&BufferedWrite) 摘要 本文主要介绍快速输入输出, 文中提到了几个IO类,这里推荐使用Buffered ...