在 PlayStation 的 Blu-ray Disc Java(BD-J)平台上,近期发现了一个由两个独立漏洞构成的组合攻击链。攻击者通过巧妙利用这些漏洞,可以成功实现Java沙箱逃逸,突破系统预设的安全限制。
漏洞一:org.dvb.io.ixc 组件权限绕过漏洞
BD-J 平台实现了两种 Ixc(Xlet 间通信)机制:org.dvb.io.ixc 和 com.sun.xlet.ixc。
在 org.dvb.io.ixc 的实现中,com.sony.gemstack.org.dvb.io.ixc.IxcProxy 类存在权限验证缺陷,使得攻击者可以在特权上下文中调用敏感方法。虽然该漏洞曾被修复,但修复措施并不彻底。通过 com.sony.gemstack.org.dvb.io.ixc.IxcProxyBuilder 构建的真实代理类,依然可以在特权上下文中执行方法调用。
这里有一个关键细节:任何实现了 java.rmi.Remote 接口的类实例都可以注册为 Ixc 服务。并且,只有声明会抛出 java.rmi.RemoteException 异常的方法才能通过 Ixc 机制被调用。
恰好,com.sun.xlet.ixc.IxcRegistryImpl 类完全满足这两个条件。攻击者可以按以下步骤操作:
- 创建一个
com.sun.xlet.ixc.IxcRegistryImpl 的子类。
- 实例化该子类。
- 通过
org.dvb.io.ixc.IxcRegistry 将这个实例注册为一个服务。
有趣的是,com.sun.xlet.ixc.IxcRegistryImpl 类内部的方法包含了严格的权限检查逻辑:
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new IxcPermission(name, "bind"));
然而,当通过 org.dvb.io.ixc 机制去调用远程对象的 bind 和 lookup 方法时,这些权限检查可以被巧妙地绕过,从而执行原本被禁止的操作。
漏洞二:com.sun.xlet.ixc 组件特权方法调用漏洞
在 com.sun.xlet.ixc 组件中,存在着另一个致命漏洞,它允许攻击者执行特权方法调用。具体问题出在 com.sun.xlet.ixc.WrappedRemote 类的 com_sun_xlet_execute 方法里,该方法在一个 AccessController.doPrivileged 代码块中调用了 remoteMethod:
AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws RemoteException {
Throwable err = null;
try {
result[0] = remoteMethod.invoke(targetNow, args);
} catch (InvocationTargetException ite) {
err = ite.getTargetException();
} catch (Throwable t) {
err = t;
}
// ...
return null;
}
},
context);
攻击者可以通过 com.sun.xlet.ixc.IxcClassLoader 注册对象时生成的存根类来访问这个关键方法。
完整的组合攻击流程
要实现沙箱逃逸,攻击者需要将上述两个漏洞串联起来,形成一个完整的攻击链:
-
第一步:构造恶意接口和实现类
首先,攻击者需要定义一个看似无害的远程接口及其实现。
public interface SystemInterface extends java.rmi.Remote {
void setSecurityManager(java.rmi.Remote sm) throws java.rmi.RemoteException;
}
public class SystemImpl implements SystemInterface {
public void setSecurityManager(java.rmi.Remote sm) {}
}
-
第二步:注册恶意服务
- 创建一个
SystemImpl 类的实例。
- 利用漏洞一(权限绕过)中提到的
com.sun.xlet.ixc.IxcRegistryImpl 子类,将这个实例注册为服务。
-
第三步:操纵方法指针,实现“狸猫换太子”
- 在生成的存根类远程对象上调用
com_sun_xlet_destroy 方法,将内部的 com_sun_xlet_method0 指针设置为 null。
- 接着调用
com_sun_xlet_init 方法,并传入一个自定义的 findMethod 方法。这个自定义方法的目的是,将系统敏感的 System.setSecurityManager 方法“偷渡”进来,并设置给 com_sun_xlet_method0。
public static Object findMethod(String cName, String mName, Object[] types)
throws NoSuchMethodException {
return System.class.getMethod(
"setSecurityManager", new Class[] { SecurityManager.class });
}
-
第四步:执行沙箱逃逸
- 此时,
com_sun_xlet_method0 已经不再指向 SystemImpl.setSecurityManager,而是指向了系统自身的 System.setSecurityManager 方法。
- 当攻击者调用远程
SystemImpl 对象的 setSecurityManager(null) 方法时,实际执行的代码是 System.setSecurityManager(null)。这个方法调用发生在 AccessController.doPrivileged 代码块内,从而成功地禁用了整个 Java 安全管理器,实现了沙箱逃逸。
漏洞影响分析
成功利用这一组合漏洞的后果非常严重:
- 完全绕过 Java 沙箱的安全限制。
- 能够在 BD-J 环境中执行任意本地代码。
- 最终获得系统级的权限访问能力。
攻击技巧(Tricks)深度总结
这次漏洞利用展示了多种高级的安全/渗透/逆向攻击技巧:
-
多漏洞协同利用策略:攻击者没有局限于单一漏洞,而是识别并组合利用了 org.dvb.io.ixc 的权限绕过和 com.sun.xlet.ixc 的特权执行这两个看似独立的漏洞。第一个漏洞为第二个漏洞创造了关键的利用条件,构建出一条完整的攻击链,实现了单一漏洞无法达成的破坏效果。
-
Java 反射机制滥用:核心攻击步骤严重依赖反射机制。通过自定义的 findMethod 函数,动态获取并劫持了 System.setSecurityManager 这一敏感系统方法的引用。这种动态操纵类方法指针的方式,巧妙绕过了编译时的类型检查和安全限制。
-
权限上下文操纵技术:准确识别并利用了 AccessController.doPrivileged 代码块。通过构造恶意调用链,最终让禁用安全管理器的关键代码在这个特权上下文中执行,从而绕过了 SecurityManager 的常规权限检查机制。
-
远程方法调用(RMI)安全缺陷利用:攻击者深刻理解了 BD-J 平台 Ixc 机制(基于 RMI)的安全边界。通过注册一个“合规”的远程接口,然后利用存根类生成和调用过程中的逻辑缺陷,欺骗系统执行了攻击者预设的恶意代码路径。
-
接口继承关系攻击:利用 Java 的接口继承特性构造恶意类层次。通过让自定义类实现 java.rmi.Remote 接口,使其获得了注册为系统服务的“资格”。再利用接口方法签名的可塑性,在运行时进行方法劫持,实现了“签名符合、行为恶意”的攻击。
这个案例是一次非常经典的深度安全研究,它提醒开发者,在实现复杂的跨组件通信和权限系统时,必须对每一个安全边界和上下文切换点进行审慎的审计。对于安全研究者而言,它展示了如何将看似微小的逻辑缺陷串联成具有重大威胁的完整攻击链。更多类似深度的技术分析与讨论,欢迎访问云栈社区的安全板块进行交流。