环境搭建

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

  • 基于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转义函数:

  1. addslashes()函数:

    能够将单引号、双引号、反斜杠和null转义

  2. 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环境搭建及代码详解+防御手段的更多相关文章

  1. 从c#角度看万能密码SQL注入漏洞

    以前学习渗透时,虽然也玩过万能密码SQL注入漏洞登陆网站后台,但仅仅会用,并不理解其原理. 今天学习c#数据库这一块,正好学到了这方面的知识,才明白原来是怎么回事. 众所周知的万能密码SQL注入漏洞, ...

  2. 利用SQL注入漏洞登录后台的实现方法

    利用SQL注入漏洞登录后台的实现方法 作者: 字体:[增加 减小] 类型:转载 时间:2012-01-12我要评论 工作需要,得好好补习下关于WEB安全方面的相关知识,故撰此文,权当总结,别无它意.读 ...

  3. 利用SQL注入漏洞登录后台的实现方法 。。。。转载

    一.SQL注入的步骤 a) 寻找注入点(如:登录界面.留言板等) b) 用户自己构造SQL语句(如:' or 1=1#,后面会讲解) c) 将sql语句发送给数据库管理系统(DBMS) d) DBMS ...

  4. SQL 注入漏洞浅研究学习

    SQL注入漏洞:Web安全方面最高危的漏洞,SQL漏洞威胁着网站后台数据的安全问题. 网上常说“万能密码”,这个万能密码则就是利用了SQL注入漏洞: ' or 1=1 -- 上述的万能密码输入在用户登 ...

  5. SQL注入漏洞技术的详解

    SQL注入漏洞详解 目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 Up ...

  6. SQL注入漏洞详解

    目录 SQL注入的分类 判断是否存在SQL注入 一:Boolean盲注 二:union 注入 三:文件读写 四:报错注入 floor报错注入 ExtractValue报错注入 UpdateXml报错注 ...

  7. 浅谈SQL注入漏洞以及防范策略

    --HeShiwei 2014-5-15 什么是SQL注入 SQL注入,指的是用户通过向登录框输入恶意字符,利用代码的字符串拼接漏洞进行网站注入攻击,最终导致整个网站用户表信息泄露的攻击方式.黑客就是 ...

  8. sql注入漏洞笔记随笔

    sql注入是从1998年出现的,是一个十分常见的漏洞,它是OWASP top10的第一名(注入) 在了解sql注入之前,我们需要先了解web框架 webapp:web网站,这种方式它采用的是B/S架构 ...

  9. PHPCMS \phpcms\modules\member\index.php 用户登陆SQL注入漏洞分析

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述2. 漏洞触发条件 0x1: POC http://localhost/p ...

随机推荐

  1. FastDFS是使用c语言编写的开源高性能分布式文件系统

    FastDFS是什么 FastDFS是使用c语言编写的开源高性能分布式文件系统 是由淘宝开发平台部资深架构师余庆开发,FastDFS孵化平台板块 他对文件进行管理,功能包括文件存储,文件同步,文件访问 ...

  2. python---replace函数

    描述 Python replace() 方法把字符串中的 old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过 max 次. 语法 replace()方法语法: st ...

  3. mitmproxy第一次尝试-猿人学第九题

    启动 mitmdump -s http_proxy.py -p 9000 替换js代码 # -*- coding: utf-8 -*- import re main_url = 'http://mat ...

  4. Spring Boot从入门到精通(十一)集成Swagger框架,实现自动生成接口文档

    Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.Swagger 是一组开源项目,其中主要要项目如下: Swagger-tools:提供各种与S ...

  5. LVM磁盘配额

    目录 一.LVM概述 1.1.逻辑卷管理 1.2.LVM机制的基本概念 二.LVM管理命令 三.磁盘配额概述 3.1.实现磁盘配额的条件 3.2.Linux磁盘限额的特点 3.3.常用命令及选项 3. ...

  6. 什么是 RFC 2544

    什么是 RFC 2544? 如果您从事网络工作,您可能听说过它,但 RFC 2544 究竟是什么呢? RFC 的全称是 Request for comment ,请求注解.是一系列收录了互联网国际标准 ...

  7. RHCSA_DAY10

    分区过程 添加新硬盘--分区--格式化文件系统--挂载使用 扇区是磁盘存储数据的最小单元,默认一个扇区可以存储512字节的数据 磁盘类型介绍 IDE接口类型:主要用于个人家用计算机领域,优点价格便宜, ...

  8. Docker 实践及命令梳理

    文档 Docker Reference Documentation Docker 从入门到实践 [中文] 安装 安装 Docker,设置开机启动,然后配置阿里云镜像加速 1. 安装 Docker Do ...

  9. 配置SSH公钥以及创建远程仓库

    一.配置SSH公钥 1.生成SSH公钥 在我们自己电脑的桌面上右键菜单,打开git命令行,输入以下命令: ssh-keygen -t rsa 一直敲回车之后,显示以下信息即表示成功生成SSH公钥,并且 ...

  10. Anaconda创建虚拟环境并使用Jupyter-notebook打开虚拟环境

    由于需要使用Tensorflow的1.xx的低版本,但是cmd下载一直报错没有解决,就想着用Anaconda,但是真实环境我已经装上Tensorflow2.0了不想换了,所以就想着再建一个python ...