
MySQL Community Server 26.7.0 - High - mysqldump --tab path leftover - client file write
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-mysqldump-tab-path
Class: File write (client) Reach: Remote (UI:R)
MySQL Community Server mysqldump 26.7.0 (06a5c1c) - Oracle
mysqldump --tab=DIR writes one .sql per table using fn_format without MY_REPLACE_DIR. A hostile SHOW TABLES name with / or .. keeps that directory. DIR is ignored. The dump UID my_fopens the path.
--tab is documented as same-machine mode because the .txt goes through server INTO OUTFILE. The .sql is still a client write.
| ID | no CVE yet |
| Class | File write (client --tab .sql) |
| Reach | Remote (victim runs mysqldump --tab against an attacker MySQL; UI:R) |
| CWE | CWE-22 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N |
| Product | MySQL Community Server mysqldump |
| Affected | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Auth | victim runs mysqldump --tab=DIR against an attacker MySQL |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only. Witness .sql outside DIR. |
Stand up a MySQL-protocol server. Answer SHOW TABLES with /abs/path or ../outside. The operator who ran mysqldump --tab=/backup testdb writes /abs/path.sql (or a path relative to cwd) as the dump UID.
Overwrite any file that UID can create. Same class as a backup client that trusts a remote filename. The .txt INTO OUTFILE path is server-side FILE. The leftover is the client .sql.
A real mysqld will not emit a table name with /. The leftover is the client.
Same 26.7.0 hunt as mysqldump SHOW TABLES overflow. Default daemon was empty. Client tools still trusted SHOW TABLES. Overflow was one leftover. --tab was the next.
static FILE *open_sql_file_for_table(const char *table, int flags) {
FILE *res;
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
convert_dirname(tmp_path, path, NullS);
res = my_fopen(fn_format(filename, table, tmp_path, ".sql",
MYF(MY_UNPACK_FILENAME | MY_APPEND_EXT)),
flags, MYF(MY_WME));
return res;
}
mysys/mf_format.cc: if dirname_part(name) is non-empty and MY_REPLACE_DIR is off, the given dir is not used.
Wrong turns already recorded: treating a real mysqld as the oracle; dying at SHOW TABLE STATUS before SHOW CREATE TABLE (the .sql opens only after CREATE succeeds); calling INTO OUTFILE .txt the leftover; a 64KiB name that re-hits the G1 overflow.
Not MariaDB CVE-2025-13699 (mariadb-dump view-name traversal). Same class, MySQL Community copy.
cd lab
./run.sh
Image mysql:26.7.0. --tab=/work/tabdir. Control stub table t writes work/tabdir/t.sql. Traversal stub table /work/oracle/MYSQL-DUMP-TAB-TRAVERSAL-WITNESS writes work/oracle/MYSQL-DUMP-TAB-TRAVERSAL-WITNESS.sql. Published 127.0.0.1:18610 / 18611. Bind it to loopback.
control-sql=yes
traversal-outside=yes
SUCCESS mysql-mysqldump-tab-path ... MYSQL-DUMP-TAB-TRAVERSAL-WITNESS
Pass MY_REPLACE_DIR into fn_format for --tab client files, or take basename of the table name first. --tab=DIR should mean DIR.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)client/mysqldump.cc open_sql_file_for_tablemysys/mf_format.cc