資料篡改即是對電腦網路資料進行修改、增加或刪除,造成資料破壞。 資料庫資料被攻擊了首先得查看是被刪除了還是被篡改了?是否有備份資料,是否能夠進行恢復並加固。 本文來自資料庫技術專家張正,主要描述了MySQL遭到攻擊篡改資料,利用從庫的備份和主庫的Binlog進行不完全恢復。
以下是作者原文:
一、發現問題
今天是2014-09-26,開發大清早就說昨晚資料庫遭到了攻擊。 資料庫中某文章表的文章內容欄位遭到篡改,全部改成了同一篇文章。
通過查看日制 發現 資料是在 2014-09-25 21:53:57 遭到篡改。
所有的內容全部被改成了如下:
subject: 桂林陽朔自助游
content:
一直都是自助游,從不喜歡?團。 去之前都是在網上做足了功課,真的是很感謝那些寫遊記寫攻略的朋友。 所以,現在也想把自己的體會和經驗寫出來,和大家分享,希望對後來的朋友有説明。
一個月前,朋友約我去陽朔一游,陽朔也是我一直想去的地方,特別是傳說中的西街。 上網搜集資料,制定出我們的行程計畫(呵呵,可能是職業習慣吧,制定計畫和行程安排是我們的強項,計劃性和靈活性是我們的特點),目的很明確,是度假休閒,不必游走于各個景點,其實我想朋友們也在很多地方都旅遊多了, 也知道有些景點是怎麼出來的,各地都一樣。
制定好主旋律後,我們的大致行程安排如下:
十九號桂林集中,二十號出發去陽朔,先去陽朔安頓下來(有些人是從桂林帶著行李在楊堤路口下車,直接先去灕江漂流,然後再去陽朔,好像節約時間,不過,我們因為沒有安排那麼滿,也不想帶著行李遊玩,所以選擇先去陽朔安頓, 和客棧老闆好好聊聊情況後,再決定具體細節)
?次度假的主要內容是:灕江漂流;遇龍河漂流(全漂),十裡畫廊 ;西街打望,發呆,西街酒吧,印象劉三姐,其他的根據情況和心情臨時決定。
我把文章貼出來,先譴責一下,很可能是某旅遊社的人為了打廣告 雇人幹的。
二、解決方法
這個庫我們是每天淩晨備份,保留30天的備份。 主庫的Binlog保留時間為7天。
因此很容易想到的方法是將從庫2014-09-25淩晨的備份拿出來恢復,然後通過主庫的Binlog通過時間段來篩選出淩晨至2014-09-25 21:53:56的所有更改,之後的資料,經業務確認,可以捨棄掉。 或者後面再通過其他方法慢慢將這部分資料找出來。 但是當務之急,是立馬恢復資料庫。
三、找備份及時間點
在備份的從庫上檢查備份:
crontab -l
#0 3 * * * /data/opdir/mysqlbak/backup_mysqldump.sh 6084 >> /data/opdir/mysqlbak/6084/mysql-bakup.log 2>& amp;1
發現備份任務讓注釋了
查看備份檔案:
<p>[root@localhost 6084]# ll</p><p>total 128</p><p>drwxr-xr-x 2 root root 4096 Aug 25 03:13 20140825</p><p>drwxr-xr-x 2 root root 4096 Aug 26 03:13 20140826</p><p>drwxr-xr-x 2 root roo t 4096 Aug 27 03:13 20140827</p><p>drwxr-xr-x 2 root root 4096 Aug 28 03:13 20140828</p><p>drwxr-x r-x 2 root root 4096 Aug 29 03:13 20140829</p><p>drwxr-xr-x 2 root root 4096 Aug 30 03:13 20140830</p>&l t;p>drwxr-xr-x 2 root root 4096 Aug 31 03:13 20140831</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;1 03: 13 20140901</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;2 03:13 20140902</p><p>drwxr-xr-x 2 r oot root 4096 Sep &nbsp;3 03:13 20140903</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;4 03:13 20140904& lt;/p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;5 03:13 20140905</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;6 03:13 20140906</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;7 03:13 20140907</p><p>drwxr-xr-x 2 root root 409 6 Sep &nbsp;8 03:13 20140908</p><p>drwxr-xr-x 2 root root 4096 Sep &nbsp;9 03:13 20140909</p>< ;p>drwxr-xr-x 2 root root 4096 Sep 10 03:13 20140910</p><p>drwxr-xr-x 2 root root 4096 Sep 11 03:13 2014091 1</p><p>drwxr-xr-x 2 root root 4096 Sep 12 03:13 20140912</p><p>drwxr-xr-x 2 root root 4096 Sep 13 03:13 20140913</p><p>drwxr-xr-x 2 root root 4096 Sep 14 03:13 20140914</p><p>drwxr-xr-x 2 root ro ot 4096 Sep 15 03:13 20140915</p><p>drwxr-xr-x 2 root root 4096 Sep 16 03:13 20140916</p><p>drwxr- xr-x 2 root root 4096 Sep 17 03:13 20140917</p><p>drwxr-xr-x 2 root root 4096 Sep 18 03:14 20140918</p>& lt;p>drwxr-xr-x 2 root root 4096 Sep 19 03:14 20140919</p><p>drwxr-xr-x 2 root root 4096 Sep 20 03:13 20140 920</p><p>drwxr-xr-x 2 root root 4096 Sep 21 03:13 20140921</p><p>drwxr-xr-x 2 root root 4096 Sep 22 03:14 20140922</p& gt;<p><strong>drwxr-xr-x 2 root root 4096 Sep 23 18:33 20140923</strong></p><p>- rw-r--r-- 1 root root 5475 Sep 23 18:33 mysql-bakup.log</p>
備份只到20140923日,下午18:33分。
備份日誌最後一段截取:
tail -n 5 mysql-bakup.log
deleting backup of 30 days ago -- 20140824
2014-09-23 18:19:12 begin backup ...
20140824 deleted OK
2014-09-23 18:33:43 end backup ...
因為這些表是在從庫備份的,而且表都是MyiSAM的表。 查看備份腳本,是先Stop Slave之後,才開始備份,因此從備份腳本輸出的日誌中找到備份開始的時間是:
2014-09-23 18:19:12
通過:
Drwxr-xr-x 2 root root 4096 Sep 23 18:33 20140923
可看到結束時間是:2014-09-23 18:33:00
現在考慮到底是以備份開始的時間:2014-09-23 18:19:12 為Start-DateTime還是以2014-09-23 18:33:00 為Start-DateTime。
前面 提到備份腳本是從庫進行備份的,是在2014-09-23 18:19:12開始的,在這個時刻備份開始,執行了Stop Slave;因此整個備份的狀態反映的是從庫2014-09-23 18:19:12 這個時間的狀態。 而且通過監控可以看到在這個時間點,從庫的延遲為0,因此可以認為這個備份就是 主庫在這個時間的備份。
NOTES:
(有人可能會因為從庫上有Binlog,從庫也會接受主庫的Binlog之類的機制而造成混淆。 這裡要結合我們具體的備份方式和恢復方式來看,以選出正確的時間點。 )
前面提到通過日誌查到遭到篡改的時間為:2014-09-25 21:53:57,因此可以將2014-09-25 21:53:56作為Stop-DateTime
因此Binlog命令應該是這樣:
<strong>mysqlbinlog --database=[db_name] --start-datetime='2014-09-23&nbsp;</strong>< strong>18:19:12</strong><strong>' --stop-datetime='2014-09-25 21:53:56'&nbsp;<br></ strong><strong>[binlog_name] > binlog_name0000x.sql</strong>
四、具體的恢復操作
清楚了這些,具體的操作就簡單了:
1.從備份機拷貝備份:
SCP<備份機IP>:/data/MySQLbak/20140923/20140923.db_name.gz <恢復測試機IP>:/data/opdir/20140926
2.恢復測試機 解壓:
gunzip 20140923.db_name.gz
3.恢復測試機導入(測試恢復庫中之前沒有db_name這個庫):
MySQL -uroot -pxxxxxx -S /tmp/MySQL.sock < 20140923.db_name
4.將主庫的Binlog拷貝到恢復測試機:
查看主庫Binlog
-rw-rw---- 1 MySQL MySQL &nbsp;87669492 Sep 23 00:00 MySQL-bin.000469<br>-rw-rw---- 1 MySQL MySQL 268436559 Sep 23 04:20 MySQL-bin.000470<br>-rw-rw---- 1 MySQL MySQL 268435558 Sep 23 17:32 MySQL-bin.000471<br>-rw-rw---- 1 MySQL MySQL &nbsp;37425262 Sep 24 00:00 MySQL-bin.000472<br>-rw-rw---- 1 MySQL MySQL 137389819 Sep 25 00:00 MyS QL-bin.000473<br>-rw-rw---- 1 MySQL MySQL 147386521 Sep 26 00:00 MySQL-bin.000474<br> 我們需要的Binlog時間段為:2014-09-23 18:28:00 至 2014-09-25 21:53:56<br>因此只需要:<br>-rw-rw---- 1 MySQL MySQL &nbsp; 37425262 Sep 24 00:00 MySQL-bin.000472<br>-rw-rw---- 1 MySQL MySQL 137389819 Sep 25 00:00 MySQL-bin.000473<br> -rw-rw---- 1 MySQL MySQL 147386521 Sep 26 00:00 MySQL-bin.000474
將這3個Binlog Copy過去:
SCP MySQL-bin.000472 <恢復測試機IP>:/data/opdir/20140926
SCP MySQL-bin.000473 <恢復測試機IP>:/data/opdir/20140926
SCP MySQL-bin.000474 <恢復測試機IP>:/data/opdir/20140926
5.使用MySQLBinlog 生成SQL腳本:
MySQLBinlog --database=[db_name] --start-datetime='2014-09-23 18:19:12' --stop-datetime='2014-09-25 21:53:56' &nbsp;<br>MySQL-bin.000472 > 472.SQL<br>MySQLBinlog --database=[db_name] --start-datetime=' 2014-09-23 18:19:12' --stop-datetime='2014-09-25 21:53:56'&nbsp;<br>MySQL-bin.000473 > 473.SQL<br >MySQLBinlog --database=[db_name] --start-datetime='2014-09-23 18:19:12' --stop-datetime='2014-09-25 21:53:56' &nbsp;<br>MySQL-bin.000474 > 474SQL
6.Binlog生成的SQL腳本導入:
待20140923.db_name導入到恢復測試庫之後,將MySQLBinlog生成的SQL腳本導入到資料庫中:
MySQL -uroot -pxxxxxx -S /tmp/MySQL.sock db_name < 472.SQL
MySQL -uroot -pxxxxxx -S /tmp/MySQL.sock db_name < 473.SQL
MySQL -uroot -pxxxxxx -S /tmp/MySQL.sock db_name < 474.SQL
7.導入完成後檢查資料正確性:
大致看一下資料的情況,然後可以通過時間欄位來看一下情況:
MySQL> select max(createtime),max(updatetime) from table_name;<br>+-----------------+-----------------+ <br>| max(createtime) | max(updatetime) |<br>+-----------------+-----------------+<br>| &nbsp; &nbsp; &nbsp;1411648043 | &nbsp; &nbsp; &nbsp;1411648043 |<br>+-----------------+-----------------+<br>1 row in set (0.00 sec)
時間差不多為 晚上20:27了
這個判斷,作為DBA,查看部分資料,只能起到輔助作用,具體的需要 到底是否OK,需要業務開發的人來判斷。
經過業務開發確認後,即可將該資料匯出後,再導入到線上主庫中。
8、將該庫匯出,並壓縮:
MySQLdump -uroot -pxxxxxx -S /tmp/MySQL.sock -q db_name table_name > table_name. SQL
壓縮:
gzip table_name. SQL
SCP 到主庫 (複製的時候,請將網路因素考慮進去,確認不會佔用過多頻寬而影響其他線上業務)
9.恢復測試的資料導入到線上主庫中:
線上主庫操作:
操作之前,最好讓開發把應用業務那段先暫停,否則可能會影響導入。 比如這個表示MyISAM的,應用那邊如果不聽有update進來,就會阻塞資料導入。
a、主庫將原始被篡改的表改名:(不要上來就drop,先rename,後續確認沒問題了再考慮drop,因為很多問題不是一瞬間就能全部反映上來的)
rename table_name to old_table_name;
b、解壓:
gunzip table_name. SQL.gz
c、導入新表資料:
MySQL -uroot -pxxxxxx -S /tmp/MySQL.sock db_name < table_name. SQL
後面就需要開發來進一步驗證資料是否 OK 了。 驗證沒問題後,再啟動應用程式。
歡迎訂閱「CSDN雲計算」微信號獲得更多雲資訊。 (責編/劉亞瓊)
歡迎關注@CSDN雲計算微博瞭解最新雲計算及大資料資訊。