
MySQL Community Server 26.7.0 - Élevé - mysqldump SHOW TABLES débordement de pile - vidage sur incident UID
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-mysqldump-show-tables-overflow
Classe : Crash Portée : Distante
MySQL Community Server mysqldump 26.7.0 (06a5c1c) - Oracle
Le mysqldump par défaut copie les noms de SHOW TABLES sans plafond NAME_LEN. getTableName renvoie un mysql_fetch_row brut. dump_all_tables_in_db fait un my_stpcpy de cette chaîne dans hash_key[2*NAME_LEN+2] et quote_name l'écrit dans un tampon de pile de 387 octets sans borne. Un serveur hostile qui répond avec un nom de table de plus de 192 octets fait planter l'UID du dump.
Un vrai mysqld n'émettra pas d'identifiants aussi longs. Le reliquat, c'est le client qui fait confiance au protocole.
| ID | pas encore de CVE |
| Classe | Crash (SIGSEGV côté client ; RCE non démontré) |
| Portée | Distante (la victime exécute mysqldump contre un MySQL attaquant ; UI:R) |
| CWE | CWE-120, CWE-121 |
| CVSS | Élevé : 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Produit | MySQL Community Server mysqldump |
| Affecté | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| Auth | la victime exécute le mysqldump par défaut contre un MySQL attaquant |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1 uniquement. Témoin de crash. Pas de payload RIP. |
Monter un serveur au protocole MySQL. Terminer le handshake. Répondre aux SET de session. Quand le client envoie show tables, renvoyer une ligne dont le nom fait des dizaines de kilo-octets.
L'opérateur qui a pointé mysqldump testdb vers cet hôte fait déborder un tampon de pile dans le processus de dump. Le labo sur mysqldump Ver 26.7.0 donne un SIGSEGV. Le contrôle fiable du pointeur d'instruction ne fait pas partie de ce pack. Le crash, si.
Même modèle de victime qu'un client de sauvegarde pointé vers un serveur malveillant. lock_tables est activé par défaut via --opt. Le débordement se produit dans cette première boucle SHOW TABLES.
J'ai mené trente-et-une chasses dans les sources de https://github.com/mysql/mysql-server tag https://github.com/mysql/mysql-server/tree/mysql-26.7.0. Les Crit/High non publiés du mysqld par défaut sont revenus vides. Les lignes CPU High Server de juillet 2026 sont fermées sur ce pin. Les outils clients étaient la classe restante, de même forme que PostgreSQL pg_basebackup suivant un chemin hostile.
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 vaut 64 * 3 = 192. hash_key fait 386 octets. quote_name dans dump_table écrit dans table_buff[NAME_LEN+3].
Fausses pistes déjà consignées : traiter un vrai mysqld comme oracle (il n'émettra pas d'identifiant de 193 octets) ; un nom de 4 Kio absorbé par real_columns[MAX_FIELDS] sur la même frame que hash_key ; compiler ASan depuis l'arbre serveur complet ; qualifier le crash de contrôle du pointeur d'instruction.
cd lab
./run.sh
Image mysql:26.7.0. Stub hostile sur compose stub:3306 (contrôle, table t) et stub:3307 (débordement, nom de 64 Kio plus témoin). Publié sur 127.0.0.1:18600 / 18601. Le lier à 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
Le contrôle affiche un en-tête de dump 26.7.0 et sort avec le code 2 sur SQL 1146. Le débordement meurt juste après show tables. Pas de LOCK TABLES sur cette connexion.
Plafonner getTableName à NAME_LEN. Donner à quote_name une longueur de tampon et refuser d'écrire au-delà. Le my_stpcpy dans hash_key devrait être une copie bornée. Un nom SHOW TABLES hostile n'est pas une table.
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)getTableName, quote_name, dump_all_tables_in_dbNAME_LENmysql_list_tables