从WMCTF2023_ez_java_again开始的RMIConnector二次反序列化学习
字数 1312 2025-08-29 22:41:24
RMIConnector二次反序列化技术分析与实战
环境搭建
- 使用CTF复现计划提供的Docker环境:
docker run -it -d -p 12345:8080 -e FLAG=flag{8382843b-d3e8-72fc-6625-ba5269953b23} lxxxin/wmctf2023_ezjavaagainrev - 访问12345端口即可启动环境
漏洞分析
初始发现
- 通过抓包发现
url参数,源代码中存在url1参数(已标记为废弃但有安全问题) - 利用
url1参数进行文件读取:/Imagefile?url1=file:///usr/local/tomcat/webapps/ROOT/WEB-INF/classes/com/ctf/help_me/%23java
反序列化过滤机制
过滤规则位于/WEB-INF/classes/config/serialkiller.xml,关键点:
- 禁用了
ChainedTransformer、TrAXFilter等关键类 - 基本封堵了CC1-6链
- 但保留了
InvokeTransformer和CC7链的入口点函数
RMIConnector二次反序列化技术
原理分析
-
核心类:
javax.management.remote.rmi.RMIConnector -
关键调用链:
findRMIServerJRMP方法:接受base64字符串,解密并进行反序列化(oin.readObject())findRMIServer方法:当path以/stub/开头时调用findRMIServerJRMPconnect方法:在rmiServer=null时调用findRMIServer
-
利用条件:
- 构造
JMXServiceURL和环境参数 - 通过CC链调用
RMIConnector的connect方法
- 构造
绕过黑名单的技术实现
-
CC6调用RMIConnector:
- 传统方法使用
TiedMapEntry传递参数 - 但题目中
TiedMapEntry被禁用
- 传统方法使用
-
CC7调用RMIConnector:
- 通过反射修改
LazyMap中hashMap1的table数组 - 获取并修改
Node对象中的key值 - 调试过程可见
key从1被替换为rmiConnector
- 通过反射修改
Payload构造要点
- 不使用
ChainedTransformer,直接组合CC7入口点和InvokeTransformer - 解决
Runtime不可序列化问题:- 采用RMI二次反序列化绕过
- 或直接加载字节码
实战步骤
-
初始信息收集:
- 通过文件读取获取
.class文件 - 分析
CmdServlet.class的反序列化逻辑
- 通过文件读取获取
-
绕过过滤:
- 利用未过滤的
InvokeTransformer和CC7入口点 - 构造不依赖
ChainedTransformer的调用链
- 利用未过滤的
-
二次反序列化触发:
- 构造合适的
RMIConnector对象 - 通过反射机制设置关键参数
- 触发
connect方法调用
- 构造合适的
参考资源
总结
RMIConnector二次反序列化技术提供了一种在严格过滤环境下实现RCE的有效途径,关键在于:
- 理解RMI连接机制和反序列化触发点
- 灵活组合未被过滤的Transformer类
- 掌握反射修改关键参数的技巧
- 合理设计二次反序列化的调用链
这种技术在CTF比赛和实际渗透测试中都有重要应用价值,特别是在传统反序列化链被封锁的情况下。