abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · mysql-mysqldump-show-tables-overflow
クラス: クラッシュ 到達性: リモート
MySQL Community Server mysqldump 26.7.0 (06a5c1c) - Oracle
デフォルトの mysqldump は SHOW TABLES の名前を NAME_LEN の上限なしでコピーする。getTableName は生の mysql_fetch_row を返す。dump_all_tables_in_db はその文字列を hash_key[2*NAME_LEN+2] に my_stpcpy し、quote_name はそれを 387 バイトのスタックバッファに境界チェックなしで書き込む。192 バイトを超えるテーブル名を返す悪意あるサーバーは、ダンプの UID をクラッシュさせる。
実際の mysqld はそれほど長い識別子を出力しない。残るのは、クライアントがプロトコルを信頼しているという問題である。
| ID | CVE 未割り当て |
| クラス | クラッシュ (クライアントの SIGSEGV、RCE は実証されていない) |
| 到達性 | リモート (被害者が攻撃者の MySQL に対して mysqldump を実行; 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 |
| 製品 | MySQL Community Server mysqldump |
| 影響バージョン | 26.7.0 (06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8) |
| 認証 | 被害者がデフォルトの mysqldump を攻撃者の MySQL に対して実行 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ。クラッシュの証拠。RIP ペイロードなし。 |
MySQL プロトコルサーバーを立ち上げる。ハンドシェイクを完了する。セッションの SET に応答する。クライアントが show tables を送信したら、名前が数十キロバイトの行を 1 行返す。
そのホストに対して mysqldump testdb を実行した運用者は、ダンププロセス内のスタックバッファをオーバーフローさせる。mysqldump Ver 26.7.0 でのラボは SIGSEGV である。信頼性の高い命令ポインタ制御はこのパックには含まれない。クラッシュは含まれる。
悪意あるサーバーに対してバックアップクライアントを向けた場合と同じ被害者モデルである。lock_tables は --opt によりデフォルトで有効。オーバーフローは最初の SHOW TABLES ループ内で発生する。
https://github.com/mysql/mysql-server のタグ https://github.com/mysql/mysql-server/tree/mysql-26.7.0 に対して 31 回のソース調査を実施した。デフォルトの mysqld で未公開の Crit/High は見つからなかった。2026 年 7 月の CPU High Server の行はこのピンではクローズされている。クライアントツールが残されたクラスであり、PostgreSQL の pg_basebackup が悪意あるパスに従うのと同じ形である。
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 は 64 * 3 = 192。hash_key は 386 バイト。dump_table 内の quote_name は table_buff[NAME_LEN+3] に書き込む。
すでに記録済みの誤った道筋: 実際の mysqld をオラクルとして扱うこと (193 バイトの識別子は出力しない); 4KiB の名前が hash_key と同じフレーム上の real_columns[MAX_FIELDS] に吸収されること; サーバーツリー全体から ASan をコンパイルすること; クラッシュを命令ポインタ制御と呼ぶこと。
cd lab
./run.sh
イメージ mysql:26.7.0。compose 上の悪意あるスタブ stub:3306 (コントロール、テーブル t) と stub:3307 (オーバーフロー、64KiB の名前と証拠)。公開 127.0.0.1:18600 / 18601。ループバックにバインドすること。
control-rc=2 control-signal=0
overflow-rc=139 overflow-signal=SIGSEGV
SUCCESS mysql-mysqldump-show-tables-overflow ... MYSQL-DUMP-SHOW-TABLES-OVERFLOW-WITNESS
コントロールは 26.7.0 のダンプヘッダを出力し、SQL 1146 で終了コード 2 を返す。オーバーフローは show tables の直後に死ぬ。その接続に LOCK TABLES はない。
getTableName を NAME_LEN で上限を設ける。quote_name にバッファ長を渡し、それを超えて書き込むことを拒否する。hash_key への my_stpcpy は境界付きコピーにすべきである。悪意ある SHOW TABLES の名前はテーブルではない。
06a5c1c99c377fc41b2eba1ea244e8b220bdc3c8)getTableName, quote_name, dump_all_tables_in_dbNAME_LENmysql_list_tables