2014-09-26 清晨,開發報告:文章表 content 字段被批量篡改為同一篇游記內容。日志定位攻擊時間:**2014-09-25 21:53:57**。架構:主庫雙實例,從庫每日冷備份,主庫 Binlog 保留 7 天。
| 節點 | 時間 | 依據 |
|---|---|---|
| 備份開始(Stop Slave) | 2014-09-23 18:19:12 | 備份腳本日志 + 目錄修改時間 |
| 備份結束 | 2014-09-23 18:33:00 | 目錄時間戳 |
| 攻擊發生 | 2014-09-25 21:53:57 | 應用日志/審計日志 |
| 恢復截止 | 2014-09-25 21:53:56 | 攻擊前 1 秒 |
關鍵判斷: 從庫備份反映的是 **Stop Slave 那一刻(18:19:12)** 的一致性快照,而非備份結束時間。
scp backup_host:/data/mysqlbak/20140923/20140923.db_name.gz recovery_host:/data/opdir/20140926/
gunzip 20140923.db_name.gz mysql -uroot -pxxx -S /tmp/mysql.sock < 20140923.db_name
# 主庫 Binlog 列表 -rw-rw---- 1 mysql mysql 37425262 Sep 24 00:00 mysql-bin.000472 -rw-rw---- 1 mysql mysql 137389819 Sep 25 00:00 mysql-bin.000473 -rw-rw---- 1 mysql mysql 147386521 Sep 26 00:00 mysql-bin.000474 # 需要 472, 473, 474 三個文件(覆蓋 18:19 → 21:53) scp mysql-bin.00047[2-4] recovery_host:/data/opdir/20140926/
mysqlbinlog --database=db_name \ --start-datetime='2014-09-23 18:19:12' \ --stop-datetime='2014-09-25 21:53:56' \ mysql-bin.000472 > 472.sql mysqlbinlog --database=db_name \ --start-datetime='2014-09-23 18:19:12' \ --stop-datetime='2014-09-25 21:53:56' \ mysql-bin.000473 > 473.sql mysqlbinlog --database=db_name \ --start-datetime='2014-09-23 18:19:12' \ --stop-datetime='2014-09-25 21:53:56' \ mysql-bin.000474 > 474.sql
mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 472.sql mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 473.sql mysql -uroot -pxxx -S /tmp/mysql.sock db_name < 474.sql
mysql> SELECT MAX(createtime), MAX(updatetime) FROM table_name; +-----------------+-----------------+ | max(createtime) | max(updatetime) | +-----------------+-----------------+ | 1411648043 | 1411648043 | -- 約 20:27,早於攻擊時間 +-----------------+-----------------+
業務方核對關鍵表數據無誤後,導出目標表:
mysqldump -uroot -pxxx -S /tmp/mysql.sock -q db_name table_name > table_name.sql gzip table_name.sql scp table_name.sql.gz master_host:/data/recovery/
-- A. 重命名原表(保留現場,不直接 DROP) RENAME TABLE table_name TO old_table_name; -- B. 導入恢復數據 gunzip table_name.sql.gz mysql -uroot -pxxx -S /tmp/mysql.sock db_name < table_name.sql
業務驗證通過後,啟動應用;觀察無異常後再清理 old_table_name。