文章总结: 该文档深度分析了Log4j2FilteredObjectInputStream绕过漏洞(CVE-2026-XXXX),影响2.11.0至2.26.1版本。漏洞核心在于FilteredObjectInputStream仅检查顶层类描述符,而Log4jLogEvent的message()方法调用MarshalledObject.get()时会创建不受过滤的ObjectInputStream,导致攻击者可通过包装恶意gadget实现远程代码执行。建议立即移除MarshalledObject白名单或改用过滤序列化通道。 综合评分: 88 文章分类: 漏洞分析,安全工具,安全开发,应用安全,解决方案
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(),自动触发不受保护的反序列化。
攻击链详解
攻击步骤
- 创建恶意对象 – 攻击者使用任意 Java 反序列化 gadget(如 CommonsCollections、JNDI 等) – 对象 不需要实现 Message 接口 – 对象 不需要在 Log4j 白名单中
- 包装成 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 - 发送到日志接收器
– 目标:任何使用
FilteredObjectInputStream的日志接收器 – 典型受害者: –ObjectInputStreamLogEventBridge(官方示例) –vertigo-analytics-server的createSerializedSocketServer– Log4j 2.14.x 及更早的TcpSocketServer - 自动执行
接收端代码: try (ObjectInputStream in = new FilteredObjectInputStream(socket.getInputStream())) { final LogEvent event = (LogEvent) in.readObject(); } ↓ 触发 LogEventProxy.readResolve() ↓ 调用 message() ↓ 执行 marshalledMessage.get()(无过滤) ↓ gadget.readObject() 执行 → RCE - 隐蔽性
– 反序列化异常被
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(最小化,推荐)
改动两个文件:
- 移除
java.rmi.MarshalledObject白名单文件:SerializationUtil.java 操作:从 REQUIRED_JAVA_CLASSES 中删除 MarshalledObject - 改用已过滤的序列化方式
java // 不使用 MarshalledObject,改用 SerializationUtil 的被过滤通道: // writeWrappedObject() / readWrappedObject() // (与 ObjectMessage 采用相同方式) // 序列化时:writeWrappedObject(message) // 反序列化时:readWrappedObject() 返回 byte[] 并通过 FOIS 过滤
优点:
- 完全移除无过滤的
get()调用 - 支持 Java 8(JEP 290 过滤器不可用)
- 简单且可靠
选项 B(结构化)
迁移到JEP 290ObjectInputFilter,该过滤器在 JDK 9+ 上可以穿透 MarshalledObject。
缺点:需要 JDK 9+,改动较大。
为什么这个漏洞很特殊
报告者强调了这与一般的”操作员误用”不同:
- 触发是自动的:Log4j 核心自己序列化
LogEventProxy,自己触发反序列化 - 不在威胁模型内:用户无法预防,因为过滤器本身有缺陷
- 完整 gadget 目录适用:payload 不受任何限制(不需实现 Message、不需在白名单中)
时间线
- 2026年8月24日:U-Sec 提交安全报告
- 报告方式:GitHub Issue(因为仓库未启用私密安全公告)
- 协调:请求安全邮箱 [email protected] 和跟踪号
PoC 代码在修复发布后或 90 天后才会公开。
这是一个设计缺陷而非配置问题,任何运行 Log4j 2.11.0 – 2.26.1 的日志网络接收服务都应立即升级。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:洛米唯熊 《Log4j2 FilteredObjectInputStream 绕过漏洞深度分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论