Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
log4j-4255 — 端到端 Docker 实验环境,复现 Apache log4j2 #4255 —— 通过 java.rmi.MarshalledObject 绕过 FilteredObjectInputStream 白名单(未过滤反序列化 → RCE),环境为 Log4j 2.26.1 / JDK 17。 | Kitploit
工具/GitHubGitHub/dinosn/log4j-4255
漏洞分析漏洞利用Web安全学习与教育二进制利用
GitHubdinosn/log4j-4255

log4j-4255

端到端 Docker 实验环境,复现 Apache log4j2 #4255 —— 通过 java.rmi.MarshalledObject 绕过 FilteredObjectInputStream 白名单(未过滤反序列化 → RCE),环境为 Log4j 2.26.1 / JDK 17。

查看仓库
2816821天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
网站
分享

log4j2 #4255 — 通过 java.rmi.MarshalledObject 绕过 FilteredObjectInputStream 白名单

一个自包含、容器化的实验环境,可端到端复现 Apache log4j2 问题 #4255,针对 JDK 17 上的 官方 Log4j 2.26.1 构件,包含阳性对照、加固后的验证基准以及经过验证的缓解措施。

⚠️ 负责任使用声明

本实验环境包含针对 当前未修补 的 Log4j 问题的 可利用的反序列化 RCE (#4255 在撰写本文时仍处于 OPEN / waiting-for-maintainer 状态;未分配 CVE)。它 完全运行在您自己机器上的一次性 Docker 容器中,除 Maven Central(用于下载官方 jar 包)外不连接任何外部资源——不会接触任何目标。

  • 原始报告者(U-Sec / 无界安全)在修复完成前暂不公开其 PoC。这是一个 独立复现,专为防御方验证和检测工程而构建。
  • 请不要针对您不拥有或未经明确授权测试的系统运行此实验。
  • 这演示的是一个应用条件性 RCE,不是通用的 Log4j RCE(请参阅影响范围)。

概要

Log4j 的 FilteredObjectInputStream(FOIS)是一个基于 resolveClass 的反序列化白名单。 其白名单包含 java.rmi.MarshalledObject。MarshalledObject 将其载荷存储为 不透明的 byte[],而 MarshalledObject.get() 会在一个全新的、未经过滤的 ObjectInputStream 上反序列化该载荷——因此白名单永远不会检查内部对象图。

Log4j 自身会触发这一点:Log4jLogEvent$LogEventProxy(自 2.8 起 LogEvent 的序列化线上形式) 将事件 Message 封装在 MarshalledObject 中,并在反序列化期间自动调用 .get() (readResolve() → message())。任何通过 FOIS 读取序列化 LogEvent 的应用程序都会对攻击者字节执行 未经过滤的反序列化——并且由于 message() 会吞掉由此产生的异常并回退到 SimpleMessage, 接收方会记录一个良性事件并继续运行。该漏洞利用是无声的。

根本原因(已针对 rel/2.26.1 验证)

实验环境运行内容

作为已弃用的 log4j-samples ObjectInputStreamLogEventBridge 的忠实替代品:一个 未认证的 TCP 接收器,通过 FOIS 读取每个连接中的一个序列化 LogEvent。 攻击者发送单个序列化对象;验证基准是一个写入目录的证明文件,该目录 仅绑定挂载到接收器容器中,因此其出现即证明代码通过反序列化在接收器内部执行。

rce = 代码已执行。reject = FOIS 在外部流上抛出异常。silent = 外部对象已处理, 但未执行代码(在更深处被阻止,或 gadget 版本是安全的)。

运行方式

root@kitploit:~
./run.sh            # 或:make run

要求:仅需 Docker(JDK 会以 eclipse-temurin:17-jdk 形式拉取)。脚本会下载 官方 jar 包并在使用前对照 Maven Central SHA-1 进行验证。可使用 LOG4J_VERSION=2.20.0 ./run.sh 固定漏洞范围内的不同 Log4j 版本。

影响与攻击方法

  • 投递方式: 向基于 FOIS 的接收器发送单个未认证的约 2.8 KB 序列化 LogEvent TCP 写入。 它不能通过记录字符串来触发(与 Log4Shell 不同)——需要原始序列化字节到达套接字桥。
  • 结果: 在接收器进程中静默执行任意命令。
  • 攻击路径: 构建 LogEvent → Log4j 的 writeReplace()/writeObject() 将 Message 封装在 MarshalledObject 中 → gadget 隐藏在其不透明的 byte[] 内 → 在接收器端, readResolve() → message() → MarshalledObject.get() 打开一个全新的未过滤流 → gadget → Runtime.exec。src/attacker/Attacker.java(poc2)将纯 CommonsCollections6 对象图拼接进 的 ,因此。

缓解措施

  • 可靠方案: 在接收器 JVM 上设置 -Djdk.serialFilter='!java.rmi.MarshalledObject'(S5)。 注意: 这也会阻止合法的序列化 LogEventProxy 对象(它们同样使用 MarshalledObject)——该方法有效,但对序列化日志传输并非透明。
  • 不可靠方案: 通用的 maxdepth/maxbytes 过滤器。进程级过滤器会传播到 内部 MarshalledObject 流,且深度在其中重新开始计算,因此 maxdepth=5 可以阻止 CC6(S6), 但浅层 gadget 仍可通过。这取决于链深度,并非边界。
  • 结构性方案: 消除 Java 序列化日志传输(使用经过认证的 TLS 上的 JSON / RFC 5424); 移除已知的 gadget 依赖;不要将遗留的序列化接收器暴露到不受信任的网络。 上游修复(根据该问题):从白名单中移除 MarshalledObject 并将封装的 消息迁移到 Log4j 的过滤式 writeWrappedObject/readWrappedObject。

影响范围与诚实声明

  • 应用条件性,而非通用 Log4j RCE。 它要求应用暴露一个未认证的基于 FOIS 的 序列化 LogEvent 接收器并且其类路径上存在可用的 gadget 版本。 普通 Log4j 部署不会运行此类接收器。
  • 核心序列化套接字服务器仅存在于 2.8.2 及之前版本(net.server.TcpSocketServer 于 2017 年移出 log4j-core;自 2.9.0 起不存在)。现代接收器属于 应用/示例代码,本实验环境正是对其建模。
  • 依赖 gadget 版本。 commons-collections 3.2.1 → RCE;3.2.2 可阻止(S7)。任何 可用的 gadget 都足够,但"存在 commons-collections"本身并不充分。
  • 实验环境中的 uid=0 是容器根用户——不存在 Docker 逃逸;RCE 以接收器进程身份运行。
  • 该原语(MarshalledObject 绕过 resolveClass 过滤器)是已知的先前技术; 请参阅 Apache 讨论 #4168 ("Log4j 2.x 反序列化加固")。Log4j 特有的自动触发机制是 #4255 的贡献。

目录结构

root@kitploit:~
run.sh                     便携式运行器(校验和固定、加固验证基准)
Makefile                   make build | run | clean
src/victim/Receiver.java   FOIS 日志接收器(ObjectInputStreamLogEventBridge 替代品)
src/attacker/Attacker.java 载荷构建器:对照、PoC-1、PoC-2(CC6 + 字节拼接)
src/attacker/EvilMessage.java  PoC-1 自包含 gadget
docs/RESULTS.md            证据矩阵 + 分析

参考

  • 问题 #4255 — https://github.com/apache/logging-log4j2/issues/4255
  • 讨论 #4168(反序列化加固)— https://github.com/apache/logging-log4j2/discussions/4168
  • Log4j CWE-502 常见问题 — https://logging.apache.org/security/faq.html
  • Apache Commons Collections 安全公告 — https://commons.apache.org/proper/commons-collections/security.html

致谢

漏洞由 U-Sec(无界安全) 在 Apache log4j2 #4255 中报告。本仓库是一个 独立的复现/验证实验环境,用于防御研究和检测工程。

下载工具
#位置缺陷
1log4j-api …/util/internal/SerializationUtil.javaREQUIRED_JAVA_CLASSES 包含 java.rmi.MarshalledObject
2log4j-api …/util/FilteredObjectInputStream.java仅重写了 resolveClass();MarshalledObject 的 objBytes 载荷对其不可见
3log4j-core …/impl/Log4jLogEvent.javaLogEventProxy.marshalledMessage 是一个 MarshalledObject<Message>
4log4j-core …/impl/Log4jLogEvent.javamessage() 调用 marshalledMessage.get()(无过滤)并吞掉所有异常
#场景受害者类路径jdk.serialFilter预期结果
S1不允许的 gadget 顶层发送+ gadget无拒绝 — FOIS 强制执行其白名单
S2相同 gadget 封装在 LogEvent 中+ gadget无rce — 自动触发(受害者上需要 gadget 类)
S3原始 CommonsCollections6 顶层log4j + cc-3.2.1无拒绝 — FOIS 阻止 CC
S4CC6 拼接进 MarshalledObject仅 log4j + cc-3.2.1无rce — 受害者上无需攻击者类
S5S4 载荷log4j + cc-3.2.1!java.rmi.MarshalledObject拒绝 — 缓解措施
S6S4 载荷log4j + cc-3.2.1maxdepth=5;maxbytes=1000000无声 — 内部流继承过滤器;CC6 过深
S7S4 载荷log4j + cc-3.2.2无无声 — 3.2.2 禁用不安全的 functor 反序列化
MarshalledObject
objBytes
受害者上无需攻击者类