小迪-day12(SQL注入简要概述)

本文最后更新于:2023年8月25日 下午

web-漏洞小迪安全.png

1、相关sql函数、语句

1.1 count()

1.1.1 count(column_name)

​ count(column_name)是计算数据库表中指定列有多少行,

​ 例:

1
SELECT COUNT(column_name) FROM table_name

1.1.2 count(*)

可以计算表中有多少行(有多少条数据)表中记录数

1.2 sum()

返回数值列的总和(只能运用于数值列)

1.3 exists()

exists()用于判断查询字句是否有记录,如果有一条或多条记录,则返回True,没有记录则返回False

EXISTS 语法

1
2
3
4
SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);

1.4 order by

1
2
3
4
5
ORDER BY 语句用于根据指定的  列  对结果集进行排序。

ORDER BY 语句默认按照升序对记录进行排序。

如果您希望按照降序对记录进行排序,可以使用 DESC 关键字。

order by 根据来进行排序,后面跟上 列名 asc(升序,默认)/desc(降序)

例如:

1
SELECT Company, OrderNumber FROM Orders ORDER BY Company

如果order by 后面的列数,大于表的列数,就会报错。

可以在order by 后面写数字,代表一个临时的列(详见标题2),如果数字数大于表的列数就会报错

例如:

image-20221108183335707

此时有1,2,3,4四个数字代表四个临时列,由于表只有三个列,所以报错

1.5 union

union 联合查询,将多条查询语句的结果集放在一个表中

1
2
3
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。

SQL UNION 语法

1
2
3
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

注释:默认地,UNION 操作符选取不同的值(结果集中没有重复的)。

​ 如果允许重复的值,请使用 UNION ALL

SQL UNION ALL 语法

1
2
3
SELECT *column_name(s)* FROM *table1*
UNION ALL
SELECT *column_name(s)* FROM *table2*;

注释:UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

1.6 group_concat()

group_concat()函数可以将组中的字符串连接成为具有各种选项的单个字符串。

最简单用法,可以把多个结果用逗号分开,形成一个字符串

2、语句 select 1 from 是什么?

1
2
select 1 from ...   与 select anycol(目的表集合中的任意一行)from ...  
select * from ... 都可以用来查询数据是否有记录

select 1 from 中的1是一常量(可以为任意数值),查到的所有行的值都是它,但从效率上来说,1>anycol>*,因为不用查字典表

测试场景:

kc表是一个数据表,假设表的行数为10行。

img

1:select 1 from kc 增加临时列,每行的列值是写在select后的数,这条sql语句中是1

2:select count(1) from kc 不管count(a)的a值如何变化,得出的值总是kc表的行数

3:select sum(1) from kc 计算临时列的和

在MySQL中用 1 测试了一下,发现结果如下:

1:测试结果,得出一个行数和kc表行数一样的临时列(暂且这么叫,我也不知道该叫什么),每行的列值是1;

2:得出一个数,该数是kc表的行数;

3:得出一个数,该数是kc表的行数;

然后我又用“2”测试,结果如下:

1:得出一个行数和kc表行数一样的临时列,每行的列值是2;

2:得出一个数,该数是kc表的行数;

3:得出一个数,该数是kc表的行数×2的数

然后我又用更大的数测试:

1:得出一个行数和kc表行数一样的临时列,每行的列值是我写在select后的数;

2:还是得出一个数,该数是kc表的行数;

3:得出一个数,该数是table表的行数×写在select后的数

结果图:

img

img
注意观察下面的两幅图的区别。

**img
**

**img

**

综上所述:

第一种的写法是增加临时列,每行的列值是写在select后的数;第二种是不管count(a)的a值如何变化,得出的值总是table表的行数;第三种是计算临时列的和

​ 当不需要知道结果是什么,只需要知道有没有结果的时候,可以使用select 1 作为子查询结果是否存在判断,这样可以提高性能。

3、SQL注入

1.1 前言

​ SQL注入漏洞将是重点部分,其中SQL注入又非常复杂,区分各种数据库类型,提交方法,数据类型等注入,我们需要按部就班的学习,才能学会相关SQL注入的核心。同样此类漏洞是WEB安全中严重的安全漏洞,学习如何利用,挖掘,修复也是很重要的。

SQL注入-小迪安全.png

​ SQL注入简单的说就是,通过添加一些sql语句在一些原有sql语句中可注入的地方,达到改写sql语句功能的目的,从而获取到数据库相关信息(高危)

1.2 MySQL注入

mysql注入-小迪.png

1.3 sqlilabs靶场搭建

下载文件放进phpstudy的www文件下,然后该配置文件,更改数据库用户名,密码,

然后进入靶场初始化数据库

实例:less-2

image-20221108184147135

查看源码:

image-20221108184248152

发现源码中$id变量接受后没有做任何限制,为恶意sql注入创造了条件。

查询数据库security可知,该数据库有4张表。

image-20221108184544871

查询users表:

image-20221108184651816

查询emails表:

image-20221108184723978

在数据库中执行如下语句:

1
select * from users where id=-1 union select 1,email_id,3 from emails limit 0,1;

可得:

image-20221108184916746

*** 如果执行如下语句:

1
select 1,email_id,3 from emails union select * from users;

则表结构为:

image-20221108190740724
1
说明:如果使用union联合查询,产生表的列名为第一条select语句查询表的列名
1
2
3
4
5
6
7
8
9
解释:
(limit 只显示第一条)
此处令id = -1 目的是使前一条select语句查询不到结果,然后显示出后面的select语句

语句:select 1,email_id,3 from emails
1:代表临时产生的一列,放在结果集的第一列,列中的值为1
email_id: 放在第二列
3:代表临时产生的一列,放在结果集的第一列,列中的值为3

将上述代码放在url中执行:可以将email查询到用户名中。

image-20221108191426881

image-20221108191320683

注: url中 %20 代表空格

1.4 测试题:

参数x有注入,以下那个注入测试正确? a,b,c

1
2
3
4
5
6
7
a. www.xiaodi8.com/news.php?y=1 and 1=1&x=2

b. www.xiaodi8.com/news.php?y=1&x=2 and 1=1

c. www .xiaodi8.com/news.php?y=1 and 1=1&x=2 and 1=1

d. www .xiaodi8.com/news.php?xx=1 and 1=1&xxx=2 and 1=1

总结:可控变量,带入数据库查询,变量未存在过滤或过滤不严谨。

1.5 判断是否存在注入点?

1
2
3
4
5
6
7
8
9
10
11
12
1、逻辑值
and 1 = 1 页面正常
and 1 = 2 页面异常
则可能存在注入点
(在url中加入)


2order by
通过order by 判断注入的字段数

order by 1,2,3,4 如果123不报错,1234报错,说明该表中只有三列,存在sql注入

image-20221108192257428 image-20221108192154448

1.6 信息收集

1
2
3
4
5
sql获得相关信息
数据库版本:version()
数据库名字:database()
数据库用户:user()
操作系统:@@version_compile_os 没有括号!
image-20221108192754857

直接在sql语句中写

1.7 MySQL 5.0+版本探测

在mysql5.0以后的版本

存在一个information_schema数据库、里面有 所有存储记录数据库名表名列名的数据库
相当于可以通过information_schema这个数据库获取到数据库下面的表名和列名。

1.7.1 获取相关信息

可以使用 . 来调用子类

1
2
3
4
5
information_schema.tables			#information_schema下面的所有表名
information_schema.columns #information_schema下面所有的列名
table_name #表名
column_name #列名
table_schema #数据库名

1、查询security数据库下的所有表

image-20221108194456608

2、查询users表下的所有列名

image-20221108195011327

1.8 墨者学院例题

image-20221109185634955

点进去发现里面有个公告

image-20221109185824251 image-20221109185845745

?id=1 疑似sql注入点

判断是否有sql注入:

1
2
?id=1 and 1=1	正常
?id=1 and 1=2 异常
image-20221109190047798

说明存在sql注入

然后判断该表的字段数

1
?id=1 order by 1		...		?id=1 order by 4

当by后面的数字为5时,页面不正常,说明字段数为4

image-20221109190305924

然后判断回显的字段是哪几个?

image-20221109190440960
1
2
使用union联合查询,注意此时让id=-1 查询不到前面的数据,则会把后半段select语句显示出来
此处说明第二列和第三列会被显示

信息搜集:

image-20221109190650848

version() 查询mysql版本号,5.0+说明此处可以使用数据库 information_schema.tables/columns

database() 查询此数据库名称

image-20221109190909704

user() 查询数据库用户名

@@version_compile_os 查询操作系统名称

image-20221109191151942

查询该数据库下的所有表,

1
2
table_name 代表	表   table_schema代表数据库,
information_schema.tables 存储了所有表信息(5.0+)

查询该表下的所有字段(列)

image-20221109191553480

1
2
column_name 代表列名
information_schema.columns 存储了所有列信息(5.0+)

group_concat(列名) 把所有结果拼接

1.9 链接

1.9.1sqlilabs靶场相关解答

https://www.yuque.com/office/yuque/0/2022/pdf/2476579/1647239035090-84752d34-43a3-4d21-953e-612760a5e4d7.pdf?from=https%3A%2F%2Fwww.yuque.com%2Fweiker%2Fxiaodi%2Fgeg7au


小迪-day12(SQL注入简要概述)
https://leekosss.github.io/2023/08/24/小迪-day12(SQL注入简要概述)/
作者
leekos
发布于
2023年8月24日
更新于
2023年8月25日
许可协议