聚焦源代码安全,网罗国内外最新资讯!

编译:代码卫士

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 插件中的堆缓冲区溢出漏洞详解相关推荐

  1. mysql identity sql_SQL Server中identity(自增)的用法详解

    一.identity的基本用法 1.含义 identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给identity修饰的字符赋值,否则编译时会报错 2.语法 列名 数据类型 ...

  2. mysql 排序后 下一条记录_什么是MySQL InnoDB 二级索引的排序?|附实例详解

    概述 今天主要给大家介绍了关于MySQL InnoDB 二级索引的排序的相关资料,通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值. 每个InnoDB表具有一个特殊的索引称为聚簇 ...

  3. mysql 分区合并_mysql中的合并表和分区表详解(经常使用的概念)

    分区表是mysql5.1之后的新特性,合并表已经存在很长时间了.这篇文章主要介绍这两个概念以及他们基本的操作. 一.合并表 合并表说实话是一种将要被淘汰的技术,但是掌握了合并表的概念再去看分区表就比较 ...

  4. mysql教程排序_MySQL中的排序函数field()实例详解

    前言 我们在日常开发过程中,排序是经常用到的,有时候有这样的需求. 比如,需要在查询结果中根据某个字段的具体值来排序.如下面例子 上面是一张个人信息 表,假如我们想按照'seiki','iris',' ...

  5. MySQL内置函数中的日期和时间函数详解

    标题:MySQL函数大全 出处:俊的博客 时间:Sat, 14 Mar 2009 14:33:22 +0000 作者:hhj 地址:http://hhj.gx.cn/post/308/ 内容: lec ...

  6. VScode 插件中 package.json 文件 activationEvents 字段详解

    一.activationEvents 插件在 VScode 中默认是没有激活的,通过 activationEvents 来进行配置: onLanguage:${language} onCommand: ...

  7. mysql的alter语句中modify,rename,change详解

    直接先抛出结论: rename和change都是用于修改名称的 rename修改的是表名称,而change修改的是表中的字段名称. 文章最后还有一些骚操作,Just for fun. modify用于 ...

  8. php 缓冲区溢出漏洞,在Linux 容器中对php-fpm缓冲区溢出漏洞的复现分析 ( CVE-2019-11043 )...

    ubuntu@vulnerable:~$ curl http://localhost Hello World ubuntu@vulnerable:~$ 存在漏洞的容器已准备就绪,为容器做个快照,以备将 ...

  9. 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 ...

最新文章

  1. 在 Linux中find命令使用技巧
  2. PPT 下载 | 神策数据张涛:企业服务客户全生命周期运营三步曲客情诊断 解决方案库...
  3. 期权定价理论及其matlab实现过程,期权定价理论及其Matlab实现过程
  4. MFC/VC++中怎样设置位图按钮并且位图不会覆盖文字——–位图按钮
  5. c# 联合halcon 基于相关性 模板匹配_机器视觉之halcon入门(5)-字符识别exe生成...
  6. [css] position的relative和absolute定位原点是哪里?
  7. 2022年数据库云管平台白皮书
  8. 运算符--位移运算符和一些其他运算符
  9. 一个类可以实现多个接口吗_java中接口的概念
  10. PHP通过传递对象参数调用asp.net Webservice 服务
  11. 服务器系统排行榜,5大主流服务器操作系统对比导购
  12. QBASIC语言程序设计 谭浩强 pdf
  13. Apache的网页与安全优化
  14. 【Configuration is still incorrect. Do you want to edit it again?】
  15. 苹果开发者账号和证书那些事
  16. 手把手教你打通车载蓝牙与手机app的音频信息传输车载反向控制手机app
  17. GPRS网络组成及接口
  18. 基于ZigBee的放射源监控系统研究
  19. cf修改游戏客户端是什么意思_穿越火线修改游戏名方法
  20. P1658 购物(贪心算法)

热门文章

  1. 在Linux上使用的10种云备份方案
  2. 2016百度之星复赛 1003 拍照 优先队列
  3. 幼谈苹果新开发语言:Swift和苹果的用心
  4. 「雅礼集训 2018 Day2」农民
  5. UiPath如何实现暂停功能?
  6. POJ 2195 Going Home(最小费用最大流)题解
  7. 微信小程序-仿淘宝(附真机测试图)(持续更新中。。。)
  8. 批量注册windows下的动态库
  9. vmware虚拟化之vswitch详细资料
  10. 不能执行已释放 Script 的代码