Log4j2FilteredObjectInputStream绕过漏洞深度分析"

admin 2026-10-19 15:29:10 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

Log4j2 FilteredObjectInputStream 绕过漏洞深度分析

洛米唯熊

2026年8月26日 15:00
福建

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

这是一个严重的远程代码执行(RCE)漏洞

影响 Log4j 2.11.0 至 2.26.1 版本。


漏洞概要

属性 详情
漏洞ID GitHub Issue #4255
报告者 U-Sec (Wujie Security)
漏洞类型 Java 反序列化过滤器绕过
影响版本 log4j-api 2.11.0 – 2.26.1 / log4j-core 2.8.0 – 2.26.1
影响范围 所有Java版本 (Java 8 及以上)
严重等级 极高 (RCE)
报告日期 2026年8月24日

技术原理详解

核心漏洞链条

这个漏洞涉及三个环节的缺陷配合:

位置:log4j-api/util/internal/SerializationUtil.java:81问题:REQUIRED_JAVA_CLASSES 包含 java.rmi.MarshalledObject

问题所在:FilteredObjectInputStream 在其 resolveClass() 方法中只验证顶层类描述符,无法检查嵌套在 MarshalledObject 内部的 objBytes 字段中的序列化数据。

位置:java.rmi.MarshalledObject.get()特性:创建一个全新的、完全不受过滤的 ObjectInputStream

当调用 MarshalledObject.get() 时,它会:

  • 构造一个 新的纯 ObjectInputStream(不是 FilteredObjectInputStream)
  • 直接反序列化内部的 byte[] 内容
  • 完全绕过过滤机制
位置:log4j-core/impl/Log4jLogEvent.java:1265-1274代码:private Message message() {    if (marshalledMessage != null) {        try {            return marshalledMessage.get();  // 无过滤的新 ObjectInputStream        } catch (final Exception ex) { /* 忽略异常 */ }    }    return new SimpleMessage(messageString);}

关键点:LogEventProxy 在反序列化时会自动调用 readResolve() → message() → marshalledMessage.get(),自动触发不受保护的反序列化。


攻击链详解

攻击步骤

  1. 创建恶意对象
       - 攻击者使用任意 Java 反序列化 gadget(如 CommonsCollections、JNDI 等)
       - 对象 不需要实现 Message 接口
       - 对象 不需要在 Log4j 白名单中
  2. 包装成 LogEventProxy
    java    final Log4jLogEvent event = Log4jLogEvent.newBuilder()        .setLoggerName(\"attacker\")        .setLevel(Level.INFO)        .setMessage(new MessageShell(gadget))  // gadget 被包装        .build();    final LogEventProxy proxy = new LogEventProxy(event, false);    // 序列化 proxy
  3. 发送到日志接收器
       - 目标:任何使用 FilteredObjectInputStream 的日志接收器
       - 典型受害者:
         - ObjectInputStreamLogEventBridge(官方示例)
         - vertigo-analytics-server 的 createSerializedSocketServer
         - Log4j 2.14.x 及更早的 TcpSocketServer
  4. 自动执行
    接收端代码:    try (ObjectInputStream in = new FilteredObjectInputStream(socket.getInputStream())) {        final LogEvent event = (LogEvent) in.readObject();    }    ↓    触发 LogEventProxy.readResolve()    ↓    调用 message()    ↓    执行 marshalledMessage.get()(无过滤)    ↓    gadget.readObject() 执行 → RCE
  5. 隐蔽性
       - 反序列化异常被 catch 块吞掉
       - 日志接收器继续正常处理
       - 攻击者发送的 payload 进入下游 appender

漏洞验证 PoC 结果

对照组测试(直接发送恶意对象)

输出:InvalidObjectException: Class is not allowed for deserialization: poc.EvilMessage结果:✓ 被正确拒绝

攻击测试(通过 LogEventProxy 包装)

[receiver] bound to 0.0.0.0 (all interfaces), no auth, port 4563[receiver] connection from /[attacker] single fire-and-forget write: 1356 bytes - done[!!] GadgetOnly.readObject() EXECUTED - no Message iface, no allowlist entry[receiver] processed event: benign message 结果:✓ 恶意对象成功执行,接收器无错误提示

影响范围

远程代码执行(RCE)

  • 所有接收序列化日志事件的服务 都面临 RCE 风险:

  • 默认不使用 TLS 或身份验证

  • 绑定到所有网卡(0.0.0.0)
  • 监听网络端口

不含 Gadget 库的情况

即使没有 Commons Collections 等库,攻击者仍可:

  • 资源耗尽 DoS:构造超大对象图(object-graph bombs)
  • 日志注入:将攻击者控制的内容注入下游日志输出

受影响的官方组件

  • log4j-core

中的 TcpSocketServer.createSerializedSocketServer()(≤ 2.14.x)
* 官方示例中的 ObjectInputStreamLogEventBridge
* 第三方 vertigo-analytics-server


根本原因分析

# 位置 缺陷
1 SerializationUtil.java:81 REQUIRED_JAVA_CLASSES 包含 java.rmi.MarshalledObject
2 FilteredObjectInputStream.java:66-72 resolveClass() 只检查顶层描述符,无法看穿 objBytes payload
3 Log4jLogEvent.java:1134 定义了 private MarshalledObject<Message> marshalledMessage 字段
4 Log4jLogEvent.java:1265-1274 message() 方法调用 marshalledMessage.get()(无过滤)且吞掉异常

修复建议

选项 A(最小化,推荐)

改动两个文件:

  1. 移除 java.rmi.MarshalledObject 白名单
    文件:SerializationUtil.java    操作:从 REQUIRED_JAVA_CLASSES 中删除 MarshalledObject
  2. 改用已过滤的序列化方式
    java    // 不使用 MarshalledObject,改用 SerializationUtil 的被过滤通道:    // writeWrappedObject() / readWrappedObject()    // (与 ObjectMessage 采用相同方式)        // 序列化时:writeWrappedObject(message)    // 反序列化时:readWrappedObject() 返回 byte[] 并通过 FOIS 过滤

优点:

  • 完全移除无过滤的 get() 调用
  • 支持 Java 8(JEP 290 过滤器不可用)
  • 简单且可靠

选项 B(结构化)

迁移到JEP 290ObjectInputFilter,该过滤器在 JDK 9+ 上可以穿透 MarshalledObject。

缺点:需要 JDK 9+,改动较大。


为什么这个漏洞很特殊

报告者强调了这与一般的\"操作员误用\"不同:

  1. 触发是自动的:Log4j 核心自己序列化 LogEventProxy,自己触发反序列化
  2. 不在威胁模型内:用户无法预防,因为过滤器本身有缺陷
  3. 完整 gadget 目录适用:payload 不受任何限制(不需实现 Message、不需在白名单中)

时间线

  • 2026年8月24日:U-Sec 提交安全报告
  • 报告方式:GitHub Issue(因为仓库未启用私密安全公告)
  • 协调:请求安全邮箱 [email protected] 和跟踪号

PoC 代码在修复发布后或 90 天后才会公开。


这是一个设计缺陷而非配置问题,任何运行 Log4j 2.11.0 - 2.26.1 的日志网络接收服务都应立即升级。


    Log4j2FilteredObjectInputStream绕过漏洞深度分析" 网络安全文章

    Log4j2FilteredObjectInputStream绕过漏洞深度分析"

    该文档深度分析了Log4j2FilteredObjectInputStream绕过漏洞(CVE-2026-XXXX),影响2.11.0至2.26.1版本。漏洞核心在于FilteredObjectInputStream仅检查顶层类描述符,而Log4jLogEvent的message()方法调用MarshalledObject.get()时会创建不受过滤的ObjectInputStream,导致攻击者可通过包装恶意gadget实现远程代码执行。建议立即移除MarshalledObject白名单或改用过滤序列化
    CVE-2026-70337PowerShell一键RCE:路径未规范化,导入即执行" 网络安全文章

    CVE-2026-70337PowerShell一键RCE:路径未规范化,导入即执行"

    CVE-2026-70337是PowerShellCore的高危路径遍历漏洞(CVSS8.8),根因在于路径解析前未规范化,攻击者可通过构造含…的恶意归档或模块,诱导用户执行Import-Module或Expand-Archive实现远程代码执行。受影响版本包括PowerShell7.4/7.5/7.6系列,官方已发布修复版本。建议立即升级并启用脚本块日志与路径越界写入告警,临时缓解措施包括收紧执行策略和归档预检。
    GoogleCloud发布智能体安全治理报告" 网络安全文章

    GoogleCloud发布智能体安全治理报告"

    GoogleCloud报告指出智能体规模化障碍从模型能力转向基础设施约束,83%组织需升级基础设施,79%技术领导者视安全治理为重大挑战.企业需确保身份可追踪,权限可收窄,运行可隔离,关键动作可确认,过程可回读,失败可回滚.上线前应评估智能体运行权限,守住身份与授权,工具与数据,运行隔离,监督与恢复四个控制点,而非依赖单一平台或提示词约束.
    评论:0   参与:  0