CVE-2021-2429:MySQL InnoDB Memcached 插件中的堆缓冲区溢出漏洞详解
聚焦源代码安全,网罗国内外最新资讯!
编译:代码卫士
2021年4月,ZDI 收到了一名匿名者提供的关于MySQL 数据库中某漏洞的报告,结果是位于 InnoDB memcached 插件中的基于堆的缓冲区溢出漏洞。该漏洞影响MySQL 版本8.0.25及之前版本,可在未认证情况下远程触发。攻击者可利用该漏洞在 MySQL 数据库服务器上执行任意代码。Oracle 公司在7月将其修复并分配编号 CVE-2021-2429。
漏洞简介
如下分析基于 MySQL Community Server 版本8.0.25,位于 memcached GET 命令中。该命令用于从表格中检索数据。在性能方面,GET 命令支持在单个 memcached 查询中提取多键值对。如下:
mysql> SELECT * FROM test.demo_test;
+----+--------------+------+------+------+
| c1 | c2 | c3 | c4 | c5 |
+----+--------------+------+------+------+
| AA | HELLO, HELLO | 8 | 0 | 0 |
+----+--------------+------+------+------+
1 row in set (0.01 sec)
telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get AA AA // query two key 'AA' within one query
VALUE AA 8 12
HELLO, HELLO
VALUE AA 8 12
HELLO, HELLO
END
GET 命令中指定的密钥被 process_get_command() 令牌化,之后在 innodb_get() 中逐个处理。
static ENGINE_ERROR_CODE innodb_get( /*=======*/ ENGINE_HANDLE *handle, /*!< in: Engine Handle */ const void *cookie, /*!< in: connection cookie */ item **item, /*!< out: item to fill */ const void *key, /*!< in: search key */ const int nkey, /*!< in: key length */ uint16_t next_get) /*!< in: has more item to get */
{
... if (report_table_switch) { // (1) char table_name[MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN]; char *name; char *dbname; conn_data = (innodb_conn_data_t *)innodb_eng->server.cookie->get_engine_specific( cookie); assert(nkey > 0); name = conn_data->conn_meta->col_info[CONTAINER_TABLE].col_name; dbname = conn_data->conn_meta->col_info[CONTAINER_DB].col_name;
#ifdef __WIN__ sprintf(table_name, "%s\%s", dbname, name);
#else snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name);
#endif // (5)
... memset(result, 0, sizeof(*result)); assert(conn_data->row_buf_used + strlen(table_name) < REC_BUF_SLOT_SIZE); // (2) memcpy((char *)(conn_data->row_buf[conn_data->row_buf_slot]) + conn_data->row_buf_used, table_name, strlen(table_name)); // (3)
... result->col_value[MCI_COL_VALUE].value_len = strlen(table_name); conn_data->row_buf_used += result->col_value[MCI_COL_VALUE].value_len; // (4)
...
}
如GET 命令中的密钥形式为 @@containers.name,则变量 report_table_switch 将被设为 true,满足 (1)处的分支。(3)处的 memcpy 将 table_name 复制到 row_buf 缓冲区。在之心相关 memcpy 之前,(2)处的代码验证 row_buf 中仍然具有足够的空间。然而,这种验证近通过 assert() 执行。由于 assert 是build中而不是在发布build中生成代码的宏,因此它可导致缓冲区溢出漏洞,在运行发布 build 时可触发。
触发条件
InnoDB memcached 插件并非默认启用,必须通过 DWITH_INNODB_MEMCACHED=ON 从源头构建 MySQL。在默认情况下,memcached 守护进程监听 TCP 和 UDP 端口11211。该 pyload 是一个单一的 GET 命令,如下所示。
get @@aaa @@aaa @@aaa ...
@@aaa 是位于 innodb_memcache 数据库中的默认列之一。
mysql> SELECT * FROM innodb_memcache.containers;
+------+-----------+-----------+-------------+---------------+-------+------------+--------------------+------------------------+
| name | db_schema | db_table | key_columns | value_columns | flags | cas_column | expire_time_column | unique_idx_name_on_key |
+------+-----------+-----------+-------------+---------------+-------+------------+--------------------+------------------------+
| aaa | test | demo_test | c1 | c2 | c3 | c4 | c5 | PRIMARY |
+------+-----------+-----------+-------------+---------------+-------+------------+--------------------+------------------------+
1 row in set (0.00 sec)
每个 @@aaa被在innodb_get()函数内的(5)处的表格名 test/demo_test替换,结果溢出内容的形式是 test/demo_testtest/demo_testtest/demo_test....。溢出的长度由攻击者控制。发送 payload 后,mysqld 进程中触发该堆缓冲区溢出漏洞。调用栈如下所示。
#0 innodb_get
#1 process_get_command
#2 process_command
#3 try_read_command
#4 conn_parse_cmd
#5 event_handler
#6 event_persist_closure
#7 event_process_active_single_queue
#8 event_process_active
#9 event_base_loop
#10 worker_libevent
#11 start_thread
#12 clone
补丁
该漏洞已在版本8.0.26中修复,非常直接。它在复制前先检查长度。
+ if (conn_data->row_buf_used + strlen(table_name) >= REC_BUF_SLOT_SIZE) {
+ conn_data->row_buf_slot++;
+
+ /* Limit the record buffer size to 16 MB */
+ if (conn_data->row_buf_slot >= 1024) {
+ err_ret = ENGINE_KEY_ENOENT;
+ goto func_exit;
+ }
+
+ if (conn_data->row_buf[conn_data->row_buf_slot] == nullptr) {
+ conn_data->row_buf[conn_data->row_buf_slot] = malloc(REC_BUF_SLOT_SIZE);
+ }
+
+ conn_data->row_buf_used = 0;
+ } memset(result, 0, sizeof(*result));
- assert(conn_data->row_buf_used + strlen(table_name) < REC_BUF_SLOT_SIZE); memcpy((char *)(conn_data->row_buf[conn_data->row_buf_slot]) +
结论
尽管 InnoDB memcached 插件并非默认启用,但尽快应用补丁无疑是明智之举。不久后出现可靠的完整 exploit 应该并不令人惊讶。
【开奖啦!!!!!】
限时赠书|《软件供应链安全—源代码缺陷实例剖析》新书上市
上次的限时赠书活动中奖名单已出炉,恭喜以下同学中奖,请微信后台私信地址,本周我们将陆续发送书籍。
@whyseu @。@HFwuhome@惊蛰 @nimo @XuZ @淡然 @Marco韬 @王孟 @Wecat@nwnλ @MOBE @湘北二两西香葱@※ @搬砖小土妞@云烟过眼 @r00t@小风 @傲雪@最好走的路是套路 @Zhao.xiaojun @浅笑淡然 @X-Star @Erick2013 @小秦同学 @X @王骏 @欢寻 @nbp@Mr. Guo
大家可移步京东电子工业出版社一睹为快!
https://item.jd.com/12927539.html 或直接点击“原文链接”购买。
如下是本书相关讲解:
推荐阅读
PHP源代码后门事件后续:用户数据库遭泄露或是元凶
RigUp 数据库暴露7.6万份美国能源行业文件
【漏洞预警】Squid缓冲区溢出及拒绝服务漏洞安全预警通告
谷歌漏洞披露规则增加30天补丁缓冲期;Reddit 公开漏洞奖励计划
原文链接
https://www.zerodayinitiative.com/blog/2021/9/2/cve-2021-2429-a-heap-based-buffer-overflow-bug-in-the-mysql-innodb-memcached-plugin
题图:Pixabay License
本文由奇安信编译,不代表奇安信观点。转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。
奇安信代码卫士 (codesafe)
国内首个专注于软件开发安全的产品线。
觉得不错,就点个 “在看” 或 "赞” 吧~
CVE-2021-2429:MySQL InnoDB Memcached 插件中的堆缓冲区溢出漏洞详解相关推荐
- mysql identity sql_SQL Server中identity(自增)的用法详解
一.identity的基本用法 1.含义 identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给identity修饰的字符赋值,否则编译时会报错 2.语法 列名 数据类型 ...
- mysql 排序后 下一条记录_什么是MySQL InnoDB 二级索引的排序?|附实例详解
概述 今天主要给大家介绍了关于MySQL InnoDB 二级索引的排序的相关资料,通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值. 每个InnoDB表具有一个特殊的索引称为聚簇 ...
- mysql 分区合并_mysql中的合并表和分区表详解(经常使用的概念)
分区表是mysql5.1之后的新特性,合并表已经存在很长时间了.这篇文章主要介绍这两个概念以及他们基本的操作. 一.合并表 合并表说实话是一种将要被淘汰的技术,但是掌握了合并表的概念再去看分区表就比较 ...
- mysql教程排序_MySQL中的排序函数field()实例详解
前言 我们在日常开发过程中,排序是经常用到的,有时候有这样的需求. 比如,需要在查询结果中根据某个字段的具体值来排序.如下面例子 上面是一张个人信息 表,假如我们想按照'seiki','iris',' ...
- MySQL内置函数中的日期和时间函数详解
标题:MySQL函数大全 出处:俊的博客 时间:Sat, 14 Mar 2009 14:33:22 +0000 作者:hhj 地址:http://hhj.gx.cn/post/308/ 内容: lec ...
- VScode 插件中 package.json 文件 activationEvents 字段详解
一.activationEvents 插件在 VScode 中默认是没有激活的,通过 activationEvents 来进行配置: onLanguage:${language} onCommand: ...
- mysql的alter语句中modify,rename,change详解
直接先抛出结论: rename和change都是用于修改名称的 rename修改的是表名称,而change修改的是表中的字段名称. 文章最后还有一些骚操作,Just for fun. modify用于 ...
- php 缓冲区溢出漏洞,在Linux 容器中对php-fpm缓冲区溢出漏洞的复现分析 ( CVE-2019-11043 )...
ubuntu@vulnerable:~$ curl http://localhost Hello World ubuntu@vulnerable:~$ 存在漏洞的容器已准备就绪,为容器做个快照,以备将 ...
- linux mysql 安装innodb_在ubuntu Mysql 5.7 安装InnoDB Memcached 插件
在ubuntu Mysql 5.7 安装Memcached 插件 参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-memcached-setup.h ...
最新文章
- 在 Linux中find命令使用技巧
- PPT 下载 | 神策数据张涛:企业服务客户全生命周期运营三步曲客情诊断 解决方案库...
- 期权定价理论及其matlab实现过程,期权定价理论及其Matlab实现过程
- MFC/VC++中怎样设置位图按钮并且位图不会覆盖文字——–位图按钮
- c# 联合halcon 基于相关性 模板匹配_机器视觉之halcon入门(5)-字符识别exe生成...
- [css] position的relative和absolute定位原点是哪里?
- 2022年数据库云管平台白皮书
- 运算符--位移运算符和一些其他运算符
- 一个类可以实现多个接口吗_java中接口的概念
- PHP通过传递对象参数调用asp.net Webservice 服务
- 服务器系统排行榜,5大主流服务器操作系统对比导购
- QBASIC语言程序设计 谭浩强 pdf
- Apache的网页与安全优化
- 【Configuration is still incorrect. Do you want to edit it again?】
- 苹果开发者账号和证书那些事
- 手把手教你打通车载蓝牙与手机app的音频信息传输车载反向控制手机app
- GPRS网络组成及接口
- 基于ZigBee的放射源监控系统研究
- cf修改游戏客户端是什么意思_穿越火线修改游戏名方法
- P1658 购物(贪心算法)