sql注入漏洞

 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行指定的SQL语句。主要原因是程序员在开发用户和数据库交互的系统时没有对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据。具体来说,它是利用现有应用程序,将SQL语句注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入SQL语句得到一个存在安全漏洞的网站上的数据,而不是按照设计者意图去执行SQL语句。

SQL注入漏洞原理

   SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。

SQL注入分类及判断

事实上SQL注入有很多种,按数据类型可以分为数字型、字符型和搜索型,按提交方式可分为GET型,POST型,Cookie型和HTTP请求头注入,按执行效果有可以分为报错注入、联合查询注入、盲注和堆查询注入,其中盲注又可分为基于bool的和基于时间的注入。从查询语句及可看出来这里是字符型的注入同时也是GET型注入和表单注入,数字型注入查询语句为:SELECT * FROM user WHERE id=1,搜索型注入为查询语句为:SELECT * FROM user WHERE search like '%1%'。

在知道查询语句的情况下我们很容易辨别是否存在注入及注入类型,很多时候我们并不知道查询语句是什么,所以我们可以这样判断,在URL或者表单中输入一个单引号或者其他特殊符号,页面出现错误说明此页面存在SQL注入,如果页面正常显示说明有字符被过滤或者不存在注入,读者可自行测试,如果存在注入可以进一步判断注入类型,在URL或者表单中输入0 or 1,如果可以查到数据,说明是数字型注入,如果输入0'or 1#,查到数据说明是字符型注入,方法不唯一。总之数字型注入不需要使用单引号闭合前面的单引号就可以执行SQL语句,而字符型必须闭合前面的单引号,然后才可以执行SQL语句,同时也需要把后面的单引号闭合,而注释就是很好的一种闭合后面的单引号的方法。
 

 sql基础语法(增、删、改、查)

 1、创建数据库、表

-- 创建一个测试的数据库
create database test charset = utf8;
-- 选择切换到这个数据库
use test;
-- 创建一个学生表
create table student(
stuid integer auto_increment primary key, -- 学生编号 数据类型 自增 主键
stuname varchar(50) not null,			  -- 学生姓名 数据类型 非空
stuage integer default 18                 -- 学生年龄 数据类型 默认18岁
);

 

2、增加、插入数据 

-- 插入几条数据 
insert into student(stuname) values("张三");
insert into student(stuname) values("张四");
insert into student(stuname) values("张五");
insert into student(stuname) values("张六");
-- 插入一个字段 
alter table student add stusex varchar(10) default '男';

sql注入漏洞_第1张图片

 3、删除

-- 删除
drop database test; -- 删除数据库
drop table student; -- 删除表
alter table student drop column stuage; -- 删除年龄字段(列)
delete from student where stuid = 3;    -- 根据索引删除某一行数据(行)

sql注入漏洞_第2张图片

 4、修改

-- 修改
update student set stusex = "女" where stuid = 2;  -- update 表名 set 需要修改的值 where 需要修改的项

sql注入漏洞_第3张图片

 5、查询

-- 查询表
select * from student; -- select 所有 from 表名
select stuname as 姓名,stusex as 性别,stuage as 年龄 from student; -- select 单独字段 as 汉译,...from 表名(as 可以不写)

sql注入漏洞_第4张图片

 常见的SQL注入类型

(1)、按注入点区分:
1、数字型注入

数字型注入主要存在于网站的url中有?id=处,如:http://xxx.com/index.php?id=1 通过改变id=的数值来判断是否有注入点,一般常见测试手段是令id等于一个不常见的大数,通过页面是否变化来判断是否存在注入点。

2、字符型注入
字符型注入常见于用户登录页面或页面url中有?username=aaa 或者?password=aaa 如:http://xxx.com/index.php?username=aaa&password=bbb,对于字符型注入,常见的手段为通过闭合符和注释符的配合,绕过用户名和密码,直接获取数据库里的账号信息。前文http://xxx.com/index.php?username=aaa&password=bbb的sql语句为select * from 表 where username=‘aaa‘ and password=‘bbb‘,而进行字符型注入时,可将url修改成,http://xxx.com/index.php?username=aaa ’ and 1=1’** **–+****&password=bbb,此时通过 ’ 的闭合和–+的注释,生产的sql语句为 select * from 表 where username=‘aaa’ and 1=1 ’ 由于1=1为永真,数据库就可能返回相关信息。

3、搜索型注入
搜索型相比于数字型和字符型而言,较为特殊点,主要是进行搜索时网站没过滤搜索关键字,常见于url中的 “keyword=” 。生成的 SQL 语句:select * from 表 where 字段 like ‘%关键字%’ ,注入时,可以构造sql注入语句:select * from 表名 where 字段 like ‘%关键字%’ and ‘%1%’=‘%1%’,进行注入。

(2)、按提交方式区分
访问网站时,浏览器只是一个传输和接收数据的工具,那么就需要将用户的操作生成数据包提交到服务器中。
1、GET 注入
按提交方式区分的话,GET注入是最简单的注入,不需要额外的工具。GET提交数据的方式的特点是将用户操作生成的语句直接显示在url上,常见于不需要保密传输的页面。GET 注入点的位置一般在参数部分。如URL为:http://xxx.com/index.php?id=1 , id =输入的内容可能是注入点。

2、POST 注入
使用POST提交的页面通常需要一定的保密性,常见于用户登录页面,用户操作生成的语句不会直接显示在url中,而是会存在于表单中,需要通过抓包才能获取,常用抓包神器BurpSuite,或者可以使用火狐浏览器通过安装hackbar等拓展抓包。抓取数据包后,可以通过修改提交的内容,结合网站页面反馈,判断能否注入。

3、Cookie 注入
Cookie,存在用户本地客户端的数据集合,HTTP 请求表单中会带上客户端的 Cookie, 注入点存在 于Cookie 当中的某个字段中。和POST一样,Cookie也要通过抓包来查看。

(3)、按页面执行反馈区分
此种注入主要是因为页面不直接反馈注入操作的内容,而常要配合各种sql函数进行,如sleep(),if(),ascll(), length()等,通过页面的反馈情况判断注入操作效果。
1、布尔注入
很多时候,sql服务器并不会直接反馈查询内容,而是通过反馈一个布尔参数给网站服务器,然后再由网站服务器将内容反馈到浏览器,也就是用户眼前,而布尔类型只有两个参数,ture和false,此时可通过配合猜解函数如sleep(),if(),ascll(), length()等,来判断注入操作的效果。
2、时间注入
和布尔注入一样,由于不直接反馈出操作的内容,从而通过执行时间来间接猜解注入效果。常用sleep()、if()、ascll()的等函数猜解,如:if(length(database()) =8,sleep(5),sleep(0))意为:如果数据库的长度等于8,那么页面休眠5秒,否则不休眠。页面休眠一般指页面处于正在刷新状态。
3、基于报错注入
页面反馈操作的错误信息,有的会直接把错误的sql语句反馈在页面中。
常见报错注入点在:单/双引号、数字型注入

SQL注入常见绕过技巧 

引号绕过


一、16进制绕过

会使用到引号的地方是在于最后的where子句中。

如下面的一条sql语句,这条语句就是一个简单的用来查选得到users表中所有字段的一条语句。

select column_name  from information_schema.tables where table_name="users"

这个时候如果引号被过滤了,那么上面的where子句就无法使用了。那么遇到这样的问题就要使用十六进制来处理这个问题了。
users的十六进制的字符串是7573657273。那么最后的sql语句就变为了:

select column_name  from information_schema.tables where table_name=0x7573657273

二、宽字节注入

宽字节注入使用场景是后台使用了一些例如addslashes()的安全函数来对单引号,双引号和反斜线进行了转义,且编码是GBK的情况

?id=1%df' union select ...

GBK编码用两个字节来表示一个汉字。\ 的GBK编码为%5C,我们在输入时就可以加上一个%df与%5c组成一个汉字“運”,这样我们的单引号就逃出了限制

逗号绕过

在使用盲注的时候,需要使用到substring(),mid(),limit。这些子句方法都需要使用到逗号。对于substring()和mid()这两个方法可以使用from to的方式来解决:

select substr(database() from 1 for 1);
select mid(database() from 1 for 1);

对于limit可以使用offset来绕过:

select * from news limit 0,1
# 等价于下面这条SQL语句
select * from news limit 1 offset 0


比较符(<,>)绕过

同样是在使用盲注的时候,在使用二分查找的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest来进行绕过了。
最常见的一个盲注的sql语句。

select * from users where id=1 and ascii(substr(database(),0,1))>64

此时如果比较操作符被过滤,上面的盲注语句则无法使用,那么就可以使用greatest来代替比较操作符了。greatest(n1,n2,n3,等)函数返回输入参数(n1,n2,n3,等)的最大值。
那么上面的这条sql语句可以使用greatest变为如下的子句:

select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64

空格绕过

空格绕过可以使用其他字符来代替空格

/**/  注释代替空格
()  括号绕过空格
编码 %a0,%0b
``(Tab上边的键)

实例

select/**/*from/**/users;
select(username)from(users);  # 注意:括号里不能有*
select%a0from%a0users;
select`*`from`users`;


随机大小写绕过

例如过滤select关键字:

SelECt * from users;


双写关键字绕过

适用于waf通过正则表达式将select等关键字过滤为空的情况

seleselectct * from users;


内联注释绕过

内联注释是把union、select等一些关键字放在/*!...*/里面来绕过waf检测

/*!select*/ * from users;


注释绕过

mysql的注释符号有:--空格、#、/**/

一些waf会将注释符号过滤,这时候可以用诸如and ‘1’ = ‘1来闭合SQL语句

# 引号闭合,$id传值 1' and '1'='1
select username,password from users where id = '$id'
#上面的sql语句变成了这样
select username,password from users where id ='1' and '1'='1'


and or关键字绕过

替换法

and ==> &&
or ==> ||

你可能感兴趣的:(sql)