SQL基于时间的盲注过程 0x00 前言 0x01 获取数据库名的长度 0x02 获取数据库名字 0x03 获取表的数量 0x04 获取表名长度 0x05 获取表名字 0x06 获取列名个数,列名长度,列名 0x07 获取数据 0x08 基于时间盲注的要点 0x09 实战演练

由于要使用到基于时间的盲注,但是我觉得基于时间的盲注其实就是基于布尔的盲注的升级版,所以我想顺便把基于布尔的盲注分析总结了;

首先我觉得基于时间的盲注和基于布尔的盲注的最直观的差别就是“参照物”不同,也就是说基于布尔的盲注,其实是可以通过页面的一些变化来进行判断结果!但是有的时候,执行一些sql语句的测试,页面不会有像布尔盲注的时候比较直观的变化,所以这个时候所谓的基于时间的盲注,也就是在基于布尔的盲注上结合if判断和sleep()函数来得到一个时间上的变换延迟的参照,也就可以让我们进行一些判断。

0x01 获取数据库名的长度

-构造的sql语句:1’ and (length(database()))> 5#
-分析:因为and后面的表达式运算的结果是bool,保证and前面的结果为真的前提下,就可以通过后面的表达式返回的bool结果来判断猜测是否正确database()这个函数的作用是获取当前的数据库名,但是我们并不能看到,所以需要通过length()函数去获取这个数据库名字的长度,通过这个长度去和我们指定的一个数比较,那么只要最后的结果为真,那就可以得到数据库名字的长度

0x02 获取数据库名字

-得到数据库名的长度过后,那就可以继续去得到数据库的具体名字,同样也是通过bool结果去判断

-构造的sql语句: 1‘ and (ascii(substr(database(),n,1)))>m #

 

分析:得到了数据库名字的具体长度,database()可以获得数据库的名字(只是无法看到),那就可以通过database()函数获得数据库名字过后,再通过substr()函数去处理这个数据库名字字符串substr(database(),n,1) 第一个参数是数据库名字,第二个参数是开始截取的字符的位置(从1开始计算),最后一个参数是截取的字符的长度。由于是想要通过bool去判断这个截取出来的具体字符是什么,所以还需要将截取出来的字符使用ascii()函数将字符转换为ascii编码的数值,然后再通过这个数据去和一个数比较,通过分别改变截取的起始位置和后面对比的数字,最后就可以把具体的数据库名字猜解出来

0x03 获取表的数量

-得到数据库表明过后,接下来就可以去获取我们查找到的数据库的表的数量

 

-构造的sql语句:1' and (select count(*) from information_schema.tables where table_schem=database())>5#

 

分析:同样也是通过最后的bool结果的真假来得到表明的数量

select count(*) from information_schema.tables where table_schem=database()

这条sql语句的作用就是从数据库information_tables里面的tables表找到table_schem字段为database()的记录的总数,也就是可以通过这个语句得到database()这个数据库里面的表的总数,因为information_schema这个数据库里面存放了所有mysql数据库服务器的相关信息,这个数据库里面的tables表里面就是存放的数据库管理系统中所有数据库的表的信息。最后得到表的数量过后,就使用这个数量结果去和一个数进行比较,那么通过对这个比较的数进行改变,就可以猜解出来这个数据库的表的数量是多少;可以通过二分法的方式进行查找

0x04 获取表名长度

-构造的sql语句:

1’ and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>5#

分析:由于一个数据库 里面创建了许多张表,所以我们需要利用limit 0,1这个命令相结合,每次只取一个表去做计算,对于其他的表以此类推;

0x05 获取表名字

-得到表名的长度过后,,就需要利用asscii()函数去得到表名的每一个字符的ascii嘛,从而得到我们想要的表名

构造的sql语句:1‘ and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),0,1)))>100

 

分析:从information_schema的tables表中的table_schema字段等于database()的所有记录中取出第一行记录的 table_name字段的值;

然后利用取出的这个值使用substr()函数分别得到表名的每个字符,然后再通过ascii()去计算这个ascii码,由于我们看不见这个ascii码是多少,由于我们能够知道布尔结果,所以就用这个计算出的ascii码去和一个数进行比较,从而可以判断出具体的ascii码是多少,也就知道了对应的字符是什么。从而猜解出数据库的表名

0x06 获取列名个数,列名长度,列名

-得到数据库的表名过后,那下一步我们就想获得对应表名的列名,也就是字段名字,那么这个时候我们就需要到information_schema数据库里的columns表里面去查询所有的表的列名相关的信息,那么获取列名的步骤也和前面的原理一样,先猜解列名的个数,获取列名的长度,然后通过获得的长度再去猜解列名

构造的sql语句:

1’ and (select count(*)from information_schema.columns where table_name=‘user’)>5#

 

构造的sql语句:

1’ and (select length(column_name)from information_schema.columns where table_name=‘user’ limit 0,1)>5#

 

构造的sql语句:

1’ and (ascii(substr((seclect columns_name from information_schema.columns where table_name='user' limit 0,1),1,1)))>100#

0x07 获取数据

-获取数据,原理同前面一样
构造的sql语句:1‘ and (ascii(substr(( select password from users limit 0,1),1,1)))=68#

0x08 基于时间盲注的要点

通过对上面的分析,我认为使用基于时间的盲注的时候,就可以将上面的构造的sql语句进行这样的变化,如下:

and if((length(database())>5),sleep(5),0)

其实也就是通过length(database())>5 返回的布尔值,然后造成时间上的延迟来判断结果,如果数据名的长度大于5是成立的,那么sleep(5)这个函数就会起作用,能够让我们感觉到返回一个页面的时间上发生了变化,通过这个变化我们就能知道我们的判断对不对。

0x09 实战演练

1通过参数提交,无论怎样的参数,页面都不发生任何变化,都是同一个页面

 

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

2、由于页面没有发生任何变化,无法做出有效判断,所以试试基于时间的盲注

构造的语句:2' and if(1=1,sleep(5),0)--+

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

通过前后对比,可以断定是存在sql注入的,因为时间上的变化可以确定我们构造的sql语句被带入了数据库执行,只是我们无法直观的看到,只能通过sleep函数来对时间上的变化造成影响,以作为我们的参照点,判断出我们想要的结果。

2、根据前面对布尔型注入和时间盲注的共同点分析,接下俩开始构造sql语句来猜解数据库名字的长度和名字

构造的sql语句:2' and if((length(database())>5),sleep(5),0)--+

判断数据库的名字是不是大于5.如果大于5,就执行sleep函数,通过查看时间知道sleep是否执行,如果被执行,那么继续改变5这个值,直到不再执行sleep

当我改到7的时候:

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

当我改到8的时候:

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

通过对比发现,当7的时候条件成立,8的时候条件不成立,也就是说数据库的长度是大于7不大于8,那长度又只能是整数,所以最后我们就成功的判断出当前的数据库的长度就是8

那我们可以将>8换成=8来验证一下:

2' and if((length(database())=8,sleep(5),0)--+

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

3、既然数据库名字的长度猜解出来了,下一步就同样使用时间盲注的方式来猜解数据库的名字

构造的sql语句如下:

2' and if(((ascii(substr(database(),m,1)))>n),sleep(5),0)--+

那么这句参数里的m,n这两个地方就是我们进行盲注的时候需要改变它们的值来测试的

m代表的是从数据库名字这个字符串的第一位开始,m变化的范围就是我们前面一部得到的数据库长度的大小:8;

n’代表的就是我们需要用来对比我们截取的字符的ascii码值的一个参考值,通过这个值的变化来最终确定我们截取的字符的ascii码值是多少,从而得到数据库名字的第一个字符

具体的操作如下:

100时:执行sleep

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

110时:执行sleep

SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

115时:没执行sleep

SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

进一步确定范围,数据库名的第一个字符的ascii码值的范围在110-115之间

那么继续更改;

112、113、114时:执行sleep

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

所以最后就很容易得到结果是:115,所以其对应的字符为:s

4、那么对于这个数据库名字的其他字符,也是通过这个方法一步步去猜解,最后就得到了我们想要的数据库名

结果是:security

通过我的数据库去验证一下,发现数据库里面确实有一个名字叫做security的数据库

 SQL基于时间的盲注过程
0x00 前言
0x01 获取数据库名的长度
0x02 获取数据库名字
0x03 获取表的数量
0x04 获取表名长度
0x05 获取表名字
0x06 获取列名个数,列名长度,列名
0x07 获取数据
0x08 基于时间盲注的要点
0x09 实战演练

那么对于表的数量,表名字的长度,以及列的相关内容和数据的相关内容,根据我前面的总结都可以使用类似的方式去推理得到,只是有点繁琐

关于今天的盲注的学习就到此结束!