震驚,我被Redis入侵了
好吧,我也做了回標(biāo)題黨,像我這么細心的同學(xué),怎么可能讓服務(wù)器被入侵呢?
其實是這樣的,昨天我和一個朋友聊天,他說他自己有一臺云服務(wù)器運行了 Redis 數(shù)據(jù)庫,有一天突然發(fā)現(xiàn)數(shù)據(jù)庫里的數(shù)據(jù)全沒了,只剩下一個奇奇怪怪的鍵值對,其中值看起來像一個 RSA 公鑰的字符串,他以為是誤操作刪庫了,幸好自己的服務(wù)器里沒啥重要的數(shù)據(jù),也就沒在意。
經(jīng)過一番攀談交心了解到,他跑了一個比較古老已經(jīng)停止維護的開源項目,安裝的舊版本的 Redis,而且他對 Linux 的使用不是很熟練。我就知道,他的服務(wù)器已經(jīng)被攻陷了,想到也許還會有不少像我這位朋友的人,不重視操作系統(tǒng)的權(quán)限、防火墻的設(shè)置和數(shù)據(jù)庫的保護,我就寫一篇文章簡單看看這種情況出現(xiàn)的原因,以及如何防范。
PS:這種手法現(xiàn)在已經(jīng)行不通了,因為新版本 Redis 都增加了 protect mode,增加了安全性,我們只能在本地簡單模擬一下,就別亂試了。
事件經(jīng)過
其實這種攻擊手法都是 2015 年的事了,那時候 Redis 的安全保護機制比較差,只能靠運維人員來合理配置以保證數(shù)據(jù)庫的安全。有段時間,全球幾萬個 Redis 節(jié)點遭到了攻擊,出現(xiàn)了上述奇怪的現(xiàn)象,所有數(shù)據(jù)被清空,只剩一個鍵叫 crackit,它的值形似 RSA 公鑰的字符串。
后來查證,攻擊者利用 Redis 動態(tài)設(shè)置配置和數(shù)據(jù)持久化的功能,把自己的 RSA 公鑰寫入到了被攻擊服務(wù)器的 /root/.ssh/authored_keys 這個文件,從而可以用私鑰直接登錄對方的 root 用戶,侵入對方系統(tǒng)。
淪陷的服務(wù)器安全防護做的很不好,具體如下:
- Redis 的端口是默認(rèn)端口,而且可以從公網(wǎng)訪問。
- Redis 還沒設(shè)密碼。
- Redis 進程是由 root 用戶啟動的。
以上每個點都是比較危險的,合在一起,那真是很致命了。且不說別人把公鑰寫到你的系統(tǒng)里,就說連上你的數(shù)據(jù)庫然后刪庫,那損失都夠大了。那么具體的流程是什么呢,下面我在本地回環(huán)地址上簡單演示一下。
本地演示
Redis 監(jiān)聽的默認(rèn)端口是 6379,我們設(shè)置它接收網(wǎng)卡 127.0.0.1 的連接,這樣我從本地肯定可以連接 Redis,以此模擬「從公網(wǎng)可以訪問 Redis」這一條件。
現(xiàn)在我是名叫 fdl 的普通用戶,我想用 ssh 登錄我系統(tǒng)上的 root 用戶,要輸入 root 的密碼,我不知道,所以沒辦法登錄。
除了密碼登錄之外,還可以使用 RSA 密鑰對登錄,但是必須要把我的公鑰存到 root 的家目錄中 /root/.ssh/authored_keys。我們知道 /root 目錄的權(quán)限設(shè)置是不允許任何其他用戶闖入讀寫的:

但是,我發(fā)現(xiàn)自己竟然可以直接訪問 Redis:

如果 Redis 是以 root 的身份運行的,那么我就可以通過操作 Redis,讓它把我的公鑰寫到 root 的家目錄中。Redis 有一種持久化方式是生成 RDB 文件,其中會包含原始數(shù)據(jù)。
我露出了邪惡的微笑,先把 Redis 中的數(shù)據(jù)全部清空,然后把我的 RSA 公鑰寫到數(shù)據(jù)庫里,這里在開頭和結(jié)尾加換行符目的是避免 RDB 文件生成過程中損壞到公鑰字符串:

命令 Redis 把生成的數(shù)據(jù)文件保存到 /root/.ssh/ 中的 authored_keys 文件中:

現(xiàn)在,root 的家目錄中已經(jīng)包含了我們的 RSA 公鑰,我們現(xiàn)在可以通過密鑰對登錄進 root 了:

看一下剛才寫入 root 家的公鑰:

亂碼是 GDB 文件的某種編碼吧,但是中間的公鑰被完整保存了,而且 ssh 登錄程序竟然也識別了這段被亂碼包圍的公鑰!
至此,擁有了 root 權(quán)限,就可以為所欲為了。。。
吸取教訓(xùn)
雖然現(xiàn)在基本不會受到這種攻擊(新版本的 Redis 沒有密碼時默認(rèn)不對外網(wǎng)開放),但是對于系統(tǒng)的安全性是每個人都應(yīng)該重視的。
我們自己折騰東西,用個低配云服務(wù)器,為了省事兒一般也不認(rèn)真配置防火墻,數(shù)據(jù)庫不設(shè)密碼或者設(shè)成 admin、root 這樣簡單的密碼,反正也沒啥數(shù)據(jù)。這樣肯定不是個好習(xí)慣。
現(xiàn)在我們的計算機系統(tǒng)越來越完善,每個成熟的項目都由最優(yōu)秀的一幫人維護,從技術(shù)上說應(yīng)該算是無懈可擊了,那么唯一可能出問題的地方就在于使用它們的人。
就像經(jīng)常看到有人的 QQ 被盜,我相信盜號的人肯定不是跑到騰訊的數(shù)據(jù)庫里盜號,肯定是 QQ 號主安全防范意識差,在哪個釣魚網(wǎng)站輸入了自己的賬號密碼,導(dǎo)致被盜。我基本沒見過微信被盜的,可能是微信弱化密碼登錄,改用二維碼掃描登錄的原因。這應(yīng)該也算是一種安全方面的考量吧,畢竟微信是有支付功能的。
上面這種騙局對于技術(shù)人來說,看看 url,瀏覽器分析一下網(wǎng)絡(luò)包就很容易識別出來,但是你還別不信,一般人真的搞不明白怎么識別釣魚網(wǎng)站和官方網(wǎng)站。就像我真沒想到都 2020 年了,還有人在找 Redis 的這個漏洞,而且還有人中招。。。
那么說回 Redis 數(shù)據(jù)庫的使用,在官網(wǎng)上明確寫出了安全防護的建議,我簡單總結(jié)一下吧:
- 不要用 root 用戶啟動 Redis Server,而且一定要設(shè)置密碼,而且密碼不要太短,否則容易被暴力破解。
- 配置服務(wù)器防火墻和 Redis 的 config 文件,盡量不要讓 Redis 與外界接觸。
- 利用 rename 功能偽裝 flushall 這種危險命令,以防被刪庫,丟失數(shù)據(jù)。