java沙盒之反反制ysoserial
字数 1492 2025-08-25 22:59:09
Java沙盒反制与反反制技术研究:以ysoserial为例
0x00 前言
本文深入分析Java反序列化工具ysoserial的安全机制,特别是其沙盒防护技术,并探讨如何实现反制与反反制。内容涵盖Registry.list()和Registry.bind()方法的反序列化漏洞利用点、ysoserial的沙盒实现原理,以及如何绕过这些安全限制。
0x01 ysoserial反制基础
关键反序列化点
ysoserial中存在两个主要的反序列化触发点:
registry.list()registry.bind()
这两个方法调用原生的RegistryImpl_Stub,触发以下调用链:
UnicastRef#invoke -> StreamRemoteCall#executeCall
最终导致反序列化操作。
沙盒限制机制
ysoserial在执行过程中会启用自定义的SecurityManager来限制命令执行:
- 在
exploit方法中,整个代码被放在沙箱内执行 - 内置了两个自定义的
SecurityManager实现
0x02 ExecCheckingSecurityManager分析
核心实现原理
ExecCheckingSecurityManager是ysoserial的关键防护机制:
public class ExecCheckingSecurityManager extends SecurityManager {
// 构造方法
public ExecCheckingSecurityManager() {
this(true);
}
// 核心检查方法
@Override
public void checkExec(String cmd) {
super.checkExec(cmd);
if (throwException) {
throw new ExecException(cmd);
}
}
// 包装执行方法
public <T> T callWrapped(Callable<T> callable) throws Exception {
SecurityManager saved = System.getSecurityManager();
try {
System.setSecurityManager(this);
return callable.call();
} finally {
System.setSecurityManager(saved);
}
}
}
关键特性
-
命令执行拦截:
- 继承自
SecurityManager - 重写
checkExec方法,在检测到命令执行时直接抛出ExecException - 构造时将
throwException参数设为true,确保严格拦截
- 继承自
-
执行环境包装:
callWrapped方法临时替换系统SecurityManager- 执行完成后恢复原始
SecurityManager - 通过
Callable接口实现代码隔离
0x03 反反制技术实现
绕过思路
-
利用
doPrivileged方法:AccessController.doPrivileged可以限制权限检查的栈帧范围- 但调用仍会在
ExecCheckingSecurityManager.checkExec中被拦截
-
外部沙盒包装:
- 在危险方法外部手动添加沙盒环境
- 隔离
list/bind方法与主执行流程
具体实现方案
final Registry sandboxRegistry = registry; // 转换为final变量
Registry receivedRegistry = new ExecCheckingSecurityManager().callWrapped(
new Callable<Registry>() {
public Registry call() throws RemoteException {
try {
sandboxRegistry.list();
} catch (ConnectIOException ex) {
ex.printStackTrace();
return LocateRegistry.getRegistry(host, port,
new RMISSLClientSocketFactory());
}
return null;
}
}
);
if (receivedRegistry != null) {
exploit(receivedRegistry, payloadClass, command);
} else {
exploit(registry, payloadClass, command);
}
实现要点
-
局部变量处理:
- 匿名内部类中使用的外部局部变量必须声明为
final - 需要预先将
registry赋值给final变量
- 匿名内部类中使用的外部局部变量必须声明为
-
异常处理:
- 在内部方法中捕获特定异常(如
ConnectIOException) - 处理SSL证书相关问题
- 在内部方法中捕获特定异常(如
-
结果传递:
- 使用新变量接收沙箱内执行结果
- 根据结果选择不同的执行路径
0x04 历史版本问题
- 2018年4月23日前的版本不支持SSL RMI
- 旧版本中
list方法可能导致反制问题 - 新版本通过
RMISSLClientSocketFactory解决安全问题
0x05 防御建议
-
对于工具开发者:
- 在所有危险RMI方法外部添加沙盒环境
- 保持工具版本更新,使用SSL RMI等安全机制
-
对于系统防御者:
- 实施严格的SecurityManager策略
- 监控和限制RMI端口访问
- 使用证书认证增强RMI安全性
0x06 总结
本文详细分析了ysoserial的沙盒防护机制及其绕过方法,关键点包括:
Registry.list()和bind()方法的反序列化漏洞利用点ExecCheckingSecurityManager的实现原理和限制- 通过外部沙盒包装实现反反制的具体方案
- 历史版本差异和SSL RMI的重要性
通过理解这些机制,安全研究人员可以更有效地进行安全测试,而防御者可以构建更完善的防护体系。