前面部分,我们已经充分了解了字典信息,接下来,我们将讲解一下这些字典信息,应该如何利用
这是我们这篇文章开始,所要了解的和深入探讨的功能,什么是探子回报,探子回报的功能是什么,我们要得到什么信息,在盲注中,如何猜测用户名和密码,所用到的函数都有哪些,对于猜测用户名和密码的步骤和效果,又如何呢
1.探子相关函数基本使用
我们先来看最基础的部分,我们通过实际的操作,给大家演示一下,所需要的函数有那些,又是如何使用的
首先,我们进入mysql之后,我们常用的就是,当前所链接的用户名到底是什么
我们要知道当前用户名是什么,我们使用函数user(),user函数,我们回车看一下,所得到的结果,select user();
我们看到是root账户,实际上,因为它是基于用户名和主机验证的,所以用户名后面跟着主机名,实际上,前面的root才是真正的用户名
除此之外,我们在sql注入中,还有一个通用的sql函数,叫current_user(),当前的用户,select current_user();
我们看到user和current_user(),得到的结果是一致的,同时还有一个叫绘画的用户,session_user(),select session_user();
它们得到的结果仍然是一致的,我们用的最多的就是第一个,user(),因为在SQL标准中还有其它的函数,这种函数在sqlserver、orcal中,一样适用
除了用户名之外,还希望了解它的版本,我们通过version(),回车,select version();
我们看到当前是5.5.47版本,得到用户名和版本信息之后,我们打开一个数据库,use hxf
往往程序链接的数据库中,肯定是有信息的,因为网站的所有信息,都保存在数据库中,那我们就需要了解网站所链接的数据库到底是什么,这数据库往往是当前的数据库,我们在上一节已经接触过了,如何获得当前的数据库名,select database();
这是数据库名,当前就是hxf数据库,往往我们希望对这些基本信息是如何处理,比如,我们获得当前的数据库,但是没有显示地方,在网页中,我们不知道它返回的是hxf,那我们要采取另外一种办法
我们可以通过猜测的办法,首先我们要知道得到的数据库,到底有多长,长度,我们使用length(),这样就得到,数据库,返回的hxf长度到底是多少,select length(database());
我们看到是3,他有三个字符,但是在注入攻击中,特别是在盲注中,即使用length()得到是3,我们仍然是不知道,它是三的,所以,我们往往跟我们前面所学到的一样,必须使用关系运算符,这种是叫比较运算符,我们把它判断出来,我们判断大于1,select length(database())>1;
这返回为真,返回为真的时候,网页显示是正常的,这时候,我们判断大于3,select length(database())>3;
我们会发现,大于3就不对了,那就说明,可能等于3,select length(database())=3;
这时候为真,这是第一步,猜测数据库名的长度是什么,长度,我们使用length()函数,当我们猜测到数据库为3的时候,我们就开始希望取第一个字符
我们就用length取左边的第一个字符,我们回车,select left(database(),1);
我们看到h,基于同样的原理,h在网页中,并不会显示给我们,需要我们去判断
比如,我们大于a,我们一直猜测下去,select left(database(),1)>‘a’;
一直为真,就一直猜测下去,当猜测到h的时候,select left(database(),1)>‘h’;
发现为假,就说明,有可能是等于h,select left(database(),1)=‘h’;
这个时候,我们就得到第一个字符,当然,这样猜测是盲注的办法
这是左边函数,但是我们,往往,并不需要左边第一个,我们需要第二个,第二个字符,我们使用另外一个函数,叫substring(),这是取子字符串的一个函数,它能从database字符串中取任意一个字符,第一个1,代表从1这个位置开始取一个字符,第一个参数是字符串,第二个参数是代表,从那个位置开始取,第三个参数是代表,取多少个字符
我们从第一个位置开始取,取一个字符,当然是h,select substring(database(),1,1)=‘h’;
这是真,我们去掉这个真,把它取出来,select substring(database(),1,1);
是h
如果从第二位,开始取一个,select substring(database(),2,1);
那么就是x
如果是第三位,取一个,select substring(database(),3,1);
那就是f
同样的道理,这个结果仍然是通过比较运算符,把它比较出来
同时,我们还可以看得到user,user是用户名和主机名的结合,那我们就要判断@的前边和后边都有什么字符,我们要知道,@所处的位置到底在那里,这个时候,我们就要用到position()函数,position输个@符号,@ in user,说明@在user中是什么位置,返回的就是@的位置,select position(’@’ in user());
我们看到是第五个位置,我们可以数一下,确实是第五个位置
我们还可以用locate(),它得到的同样是位置的信息,它的用法和position不太一样,第一个输@,第二个输user(),select locate(’@’,user());
返回的同样是5,locate()函数第一个是用查找的字符,第二个是要查找所要查找的字符串是什么
接下来,我们概括一下
User()、current_user()、session_user() 返回当前连接的用户名(包含主机名)
version() 数据库版本号
database() 当前连接的数据库名
length() 计算字符串长度
left() 取最左边的字符
substring() 取字符串中任意长度字符串
position() 返回字符所在字符串中的位置
locate()返回字符所在字符串中的位置
position()和locate()的功能是一样的
2.什么是探子回报
User(),version()
探子:测试程序是否同时对函数,子查询,括号等是否过滤,得出的结果是否令人满意
我们接下来,通过一个网页演示一下
当前的网页执行的结果是正常的,我们看到有两页
我们往往是执行user(),如果为真,我们通常是通过长度的办法,length(),大于10,回车,and length(user())>10
我们看到可能已经执行了,说明对user、length、函数、子查询、括号,并没有屏蔽掉
甚至,我们可以证实一下,大于15的时候,and length(user())>15
我们发现这是空的,说明用户名的长度不是大于15,而是小于等于15,如果等于15,我们还可以验证一下,and length(user())=15
这就说明用户名的长度是15
这种user(),实际上相当于是探子
1.两个都是SQL99标准中通用的函数,不同的数据库返回值都各有特征,进而推断是什么数据库类型。
如user()函数返回情况:
mysql返回root@localhost
oracle返回sys
sqlserver返回sa
2.执行成功,即探子回报。说明程序对函数,括号()和子查询并未做过滤,可能可以执行函数、子查询等复杂逻辑
执行失败,探子没有回报,基本上说明注入攻击困难或者注入可能性很小
3.盲注中如何猜测用户名密码
我们来实际操作一下
第一步,我们先猜测这个用户名的长度,我们最好是采用分半的办法,and length(user())>10
当我们执行,发现网页执行成功的时候,显然,这种办法是正确的,就说明user的长度就是大于10
我们再跳一级到20,and length(user())>20
如果网页显示不正常,我们就会发现,长度在10和20之间,我们采取折半的办法,选15,and length(user())>15
大于15,我们发现,还不对,那就说明这个长度在10和15之间
这个时候,我们就逐个的去相等猜测,因为只有几个而已吗,and length(user())=15
当15的时候,我们就会发现网页显示是正常的,这就说明用户名的长度是15个字符
这是第一步,用户名还包括了主机名,那我们就需要知道主机名中的@符号,它在那个位置,and position(’@’ in user())>10
我们发现错了,网页显示是不正常的,那我们试一下大于5,and position(’@’ in user())>5
我们发现网页显示是正常的,那就说明@符号在五后边,逐个猜测,它可能在六,and position(’@’ in user())=6
那么可能就是在六,假如等于七,and position(’@’ in user())=7
我们发现等于七的时候,就不正常,说明@符号在第六个位置,就说明用户名的前半部分就是五个字符
所以第三步,我们逐个猜测,把前面五个字符都给取出来
我们先取出左边的一个字符,我们直接大于t字符,and left(user(),1)>‘t’
我们发现显示是正常的
那我们输入y,and left(user(),1)>‘y’
这也正常的,实际上是我跳过了很多个字符,实际的操作过程中,可能需要我们从a字符开始,一个个的试过去,这需要重举的办法,那登于z呢,and left(user(),1)=‘z’
我们会发现等于z是正常的,这就说明用户名的第一个字符是z,我们还可以验证一下,等于y是报错的,或显示不正常的,and left(user(),1)=‘y’
我们看到网页显示是报错的,所以第一个字符应该是z,这是我们如何猜测用户名的一个办法
用户名第二个字符,我们通过substring办法,从第二个字符,取一个字符,同样的道理,我们仍然是通过比较运算符的办法,比如我们是否大于u,and substring(user(),2,1)>‘u’
很显然这是错的,那我们就小于u,and substring(user(),2,1)<‘u’
同样通过重举的办法,这个重举就不为大家演示了
我们概括一下
1.先猜测用户名有多少个字符
select * from users where uid=10003 and length(user())>4;
这个select 在url中,我们是看不到的,我们拼接的其实是and length(user())>4,后面才是我们拼接的
select * from users where uid=10003 and position(’@’ in user())>1;
select * from users where uid=10003 and position(’@’ in user())=4;
它到底是多少个,在那里,得到之后,特别是网页显示正常的时候,这是我们对结果的验证,确认它在第几位
3.用户名的5个字符中,逐个猜测
select * from users where uid=10003 and left(user(),1)=‘h’;
select * from users where uid=10003 and substring(user(),2,1)=‘x’;
比如left(),猜测第一个,substring可以去除任意一个字符,进行判断
这种方法同样用于盲注中猜测数据库名,表名,字段和密码等。
由于穷举法太累,可以借助SQL注入工具来替代人工的办法。
4.小结
常用函数有哪些?
Version() User()
Database() substring()
position() locate()
Left current_user()
Session_user()
这些函数对我们猜测用户名和密码,非常有用,同时对其它的应用,也有很大的意义,比如时间窃取