MySQL Community Server 26.7.0 mysqldump SHOW TABLES Stack Buffer Overflow
Summary
Why it matters
- Vendor
- Oracle
- Product
- MySQL Community Server
- Affected versions
- 26.7.0
- CVSS
- 8.8
- Published
- Collected
📦 Full-Text Content Snapshot
R2 Archive · Full Article PreservedAuthor: abraxas · Source: github.com/abraxas/mysql-mysqldump-show-tables-overflow
Class: Crash Reach: Remote MySQL Community Server mysqldump 26.7.0 (06a5c1c) - Oracle
Default mysqldump copies SHOW TABLES names with no NAME_LEN cap. getTableName returns a raw mysql_fetch_row. dump_all_tables_in_db my_stpcpys that string into hash_key[2*NAME_LEN+2] and quote_name writes it into a 387-byte stack buffer with no bound. A hostile server that answers a table name longer than 192 bytes crashes the dump process.
A real mysqld will not emit identifiers that long. The leftover is the client trusting the protocol.
| Field | Detail |
|---|---|
| ID | no CVE yet |
| Class | Crash (client SIGSEGV; not demonstrated RCE) |
| Reach | Remote (victim runs mysqldump against an attacker MySQL; UI:R) |
| CWE | CWE-120, CWE-121 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Product | MySQL Community Server mysqldump |
| Affected | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Auth | victim runs default mysqldump against an attacker MySQL |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only. Crash witness. No RIP payload. |
What an attacker can do
Stand up a MySQL-protocol server. Complete the handshake. Answer session SETs. When the client sends show tables, return one row whose name is tens of kilobytes long.
The operator who pointed mysqldump testdb at that host overflows a stack buffer in the dump process. Lab on mysqldump Ver 26.7.0 is SIGSEGV. Reliable instruction-pointer control is not part of this pack. The crash is.
Same victim model as a backup client pointed at a malicious server. lock_tables is default via --opt. The overflow is in that first SHOW TABLES loop.
How I found it
I ran thirty-one source hunts of mysql-server tag mysql-26.7.0. Default mysqld unpublished Crit/High came back empty. July 2026 CPU High Server rows are closed on this pin. Client tools were the leftover class, same shape as PostgreSQL pg_basebackup following a hostile path.
static char *getTableName(int reset) {
static MYSQL_RES *res = nullptr;
MYSQL_ROW row;
if (!res) {
if (!(res = mysql_list_tables(mysql, NullS))) return (nullptr);
}
if ((row = mysql_fetch_row(res))) return ((char *)row[0]);
}static char *quote_name(char *name, char *buff, bool force) {
char *to = buff;
const char qtype = ansi_quotes_mode ? '"' : '`';
if (!force && !opt_quoted && !test_if_special_chars(name)) return name;
*to++ = qtype;
while (*name) {
if (*name == qtype) *to++ = qtype;
*to++ = *name++;
}
}NAME_LEN is 64 * 3 = 192. hash_key is 386 bytes. quote_name in dump_table writes into table_buff[NAME_LEN+3].
Wrong turns already recorded: treating a real mysqld as the oracle (it will not emit a 193-byte identifier); a 4KiB name absorbed by real_columns[MAX_FIELDS] on the same frame as hash_key; compiling ASan from the full server tree; calling the crash instruction-pointer control.
Lab
cd lab
./run.shImage mysql:26.7.0. Hostile stub on compose stub:3306 (control, table t) and stub:3307 (overflow, 64KiB name plus witness). Published 127.0.0.1:18600 / 18601. Bind it to loopback.
control-rc=2 control-signal=0
overflow-rc=139 overflow-signal=SIGSEGV
SUCCESS mysql-mysqldump-show-tables-overflow ... MYSQL-DUMP-SHOW-TABLES-OVERFLOW-WITNESSControl prints a 26.7.0 dump header and exits 2 on SQL 1146. Overflow dies right after show tables. No LOCK TABLES on that connection.
The fix
Cap getTableName at NAME_LEN. Give quote_name a buffer length and refuse to write past it. my_stpcpy into hash_key should be a bounded copy. A hostile SHOW TABLES name is not a table.
References
- https://github.com/mysql/mysql-server tag mysql-26.7.0 (
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) - client/mysqldump.cc
getTableName,quote_name,dump_all_tables_in_db - include/mysql_com.h
NAME_LEN - libmysql/libmysql.cc
mysql_list_tables
📦 Full-Text Markdown Snapshot archived by Phying News · Original source: github.com
---
id: 9062
canonical_url: "https://phying.com/item/9062"
title: "MySQL Community Server 26.7.0 mysqldump SHOW TABLES Stack Buffer Overflow"
type: "vulnerability"
cve: null
cvss: 8.8
severity: "high"
vendor: "Oracle"
product: "MySQL Community Server"
affected_versions: "26.7.0"
source_domain: "github.com"
source_url: "https://github.com/abraxas/mysql-mysqldump-show-tables-overflow"
published_at: "2026-10-07T00:36:57Z"
snapshot_at: "2026-10-26T05:50:00Z"
archived_by: "Phying News (https://phying.com/item/9062)"
lang: "en"
---
# mysql-mysqldump-show-tables-overflow
*Author: abraxas · Source: [github.com/abraxas/mysql-mysqldump-show-tables-overflow](https://github.com/abraxas/mysql-mysqldump-show-tables-overflow)*
**Class:** Crash
**Reach:** Remote
**MySQL Community Server** `mysqldump` `26.7.0` (`06a5c1c`) - Oracle
Default `mysqldump` copies `SHOW TABLES` names with no `NAME_LEN` cap. `getTableName` returns a raw `mysql_fetch_row`. `dump_all_tables_in_db` `my_stpcpy`s that string into `hash_key[2*NAME_LEN+2]` and `quote_name` writes it into a 387-byte stack buffer with no bound. A hostile server that answers a table name longer than 192 bytes crashes the dump process.
A real `mysqld` will not emit identifiers that long. The leftover is the client trusting the protocol.
| Field | Detail |
|---|---|
| ID | no CVE yet |
| Class | **Crash** (client SIGSEGV; not demonstrated RCE) |
| Reach | **Remote** (victim runs `mysqldump` against an attacker MySQL; UI:R) |
| CWE | [CWE-120](https://cwe.mitre.org/data/definitions/120.html), [CWE-121](https://cwe.mitre.org/data/definitions/121.html) |
| CVSS | **High: 8.8** `CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H` |
| Product | [MySQL Community Server](https://github.com/mysql/mysql-server) `mysqldump` |
| Affected | **26.7.0** (`06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8`) |
| Auth | victim runs default `mysqldump` against an attacker MySQL |
| License | GNU Affero GPL v3.0 |
| Lab | `127.0.0.1` only. Crash witness. No RIP payload. |
## What an attacker can do
Stand up a MySQL-protocol server. Complete the handshake. Answer session `SET`s. When the client sends `show tables`, return one row whose name is tens of kilobytes long.
The operator who pointed `mysqldump testdb` at that host overflows a stack buffer in the dump process. Lab on `mysqldump Ver 26.7.0` is **SIGSEGV**. Reliable instruction-pointer control is not part of this pack. The crash is.
Same victim model as a backup client pointed at a malicious server. `lock_tables` is default via `--opt`. The overflow is in that first `SHOW TABLES` loop.
## How I found it
I ran thirty-one source hunts of [mysql-server](https://github.com/mysql/mysql-server) tag [mysql-26.7.0](https://github.com/mysql/mysql-server/tree/mysql-26.7.0). Default `mysqld` unpublished Crit/High came back empty. July 2026 CPU High Server rows are closed on this pin. Client tools were the leftover class, same shape as PostgreSQL `pg_basebackup` following a hostile path.
```c
static char *getTableName(int reset) {
static MYSQL_RES *res = nullptr;
MYSQL_ROW row;
if (!res) {
if (!(res = mysql_list_tables(mysql, NullS))) return (nullptr);
}
if ((row = mysql_fetch_row(res))) return ((char *)row[0]);
}
```
```c
static char *quote_name(char *name, char *buff, bool force) {
char *to = buff;
const char qtype = ansi_quotes_mode ? '"' : '`';
if (!force && !opt_quoted && !test_if_special_chars(name)) return name;
*to++ = qtype;
while (*name) {
if (*name == qtype) *to++ = qtype;
*to++ = *name++;
}
}
```
`NAME_LEN` is `64 * 3 = 192`. `hash_key` is 386 bytes. `quote_name` in `dump_table` writes into `table_buff[NAME_LEN+3]`.
Wrong turns already recorded: treating a real `mysqld` as the oracle (it will not emit a 193-byte identifier); a 4KiB name absorbed by `real_columns[MAX_FIELDS]` on the same frame as `hash_key`; compiling ASan from the full server tree; calling the crash instruction-pointer control.
## Lab
```bash
cd lab
./run.sh
```
Image `mysql:26.7.0`. Hostile stub on compose `stub:3306` (control, table `t`) and `stub:3307` (overflow, 64KiB name plus witness). Published `127.0.0.1:18600` / `18601`. Bind it to loopback.
```
control-rc=2 control-signal=0
overflow-rc=139 overflow-signal=SIGSEGV
SUCCESS mysql-mysqldump-show-tables-overflow ... MYSQL-DUMP-SHOW-TABLES-OVERFLOW-WITNESS
```
Control prints a 26.7.0 dump header and exits 2 on SQL 1146. Overflow dies right after `show tables`. No `LOCK TABLES` on that connection.
## The fix
Cap `getTableName` at `NAME_LEN`. Give `quote_name` a buffer length and refuse to write past it. `my_stpcpy` into `hash_key` should be a bounded copy. A hostile `SHOW TABLES` name is not a table.
## References
- [https://github.com/mysql/mysql-server](https://github.com/mysql/mysql-server) tag [mysql-26.7.0](https://github.com/mysql/mysql-server/tree/mysql-26.7.0) (`06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8`)
- [client/mysqldump.cc](https://github.com/mysql/mysql-server/blob/mysql-26.7.0/client/mysqldump.cc) `getTableName`, `quote_name`, `dump_all_tables_in_db`
- [include/mysql_com.h](https://github.com/mysql/mysql-server/blob/mysql-26.7.0/include/mysql_com.h) `NAME_LEN`
- [libmysql/libmysql.cc](https://github.com/mysql/mysql-server/blob/mysql-26.7.0/libmysql/libmysql.cc) `mysql_list_tables`
---
> 📦 **Full-Text Markdown Snapshot** archived by [Phying News](https://phying.com/item/9062) · Original source: [github.com](https://github.com/abraxas/mysql-mysqldump-show-tables-overflow)