java – 在SecurityManager下创建对象时的NoClassDefFoundError

我正在尝试通过在非常严格的SecurityManager下运行处理用户提供的内容的代码来保护我的应用程序.它的AccessController.doPrivileged()开启了它的头 – 通常这用于提供具有额外权限的代码块,但我用它来将代码块约束到一个非常小的沙箱.

在我需要调用构造函数之前,一切都很好.然后我需要读取世界的访问权限. (或至少在我的类路径中的所有.jar,.class和.property文件.)我不能只授予对<>的读访问权限.因为那是我想要避免的. (例如,尝试读取/ etc / passwd的XEE攻击.)我认为这无论如何都不够.

我可以将一些构造函数移出SecurityManager块,但有些是不可避免的,因为它是一个SAX解析器,需要在通过树时创建对象.

想法?

解决方法:

我找到了90%的回答.简短的回答是我们需要设置很多权限,但这个过程很明显,很容易隐藏在某个实用程序类中.如果它可以在某个标准的地方使用它会很好,但是哦.叹了口气.

我们需要做的就是检查类路径和ext目录的系统属性(并为它们添加FilePermissions(只读)),制作必要的SecurityPermissions(只读),最后为所有系统添加PropertyPermissions(只读)属性.剩下的就是一些非常明显的权限,例如,授予临时目录r / w / d(但不执行)权限,授予对localhost的“解析”权限等.

一个非常安全的沙箱可能不希望所有系统属性都可读,但这很容易修复并留给读者.

public class LoggingSecurityManager extends SecurityManager {
    private AccessControlContext ctx;
    private Properties properties = new Properties;
    private Set missingProperties = new HashSet();

    public LoggingSecurityManager() {
        properties.add(
            new FilePermission(System.get("java.io.tmpdir") + "/-", "read,write,delete"));

        // maybe...
        properties.add(
            new FilePermission(System.get("user.home") + "/-", "read,write,delete"));

        addSystemPropertyPermissions();
        addSecurityPermissions();
        addClassPathPermissions();
        addOtherPropertyPermissions();

        permissions.add(new RuntimePermission("accessClassInPackage.sun.reflect"));
        permissions.add(new RuntimePermission("accessClassInPackage.sun.jdbc.odbc"));
        permissions.add(new RuntimePermission("accessClassInPackage.sun.security.provider"));
        permissions.add(new SocketPermission("localhost", "resolve"));
        permissions.add(new NetPermission("getProxySelector"));

        ctx = new AccessControlContext(new ProtectionDomain[] {
            new ProtectionDomain(null, permissions)
        });
    }

    /**
     * Add read-only permission to read system properties.
     * We may want to filter this list to remove sensitive information
     */
    public void addSystemPropertyPermissions() {
        for (Object key : Collections.list(System.getProperties().keys())) {
            permissions.add(new PropertyPermission((String) key, "read"));
        }
    }

    /**
     * Add read-only permissions for initializing security.
     */
    public void addSecurityPermissions() {
        permissions.add(new SecurityPermission("getPolicy"));
        permissions.add(new SecurityPermission("getProperty.random.source"));
        permissions.add(new SecurityPermission("getProperty.securerandom.source"));

        for (int i = 1; i < 10; i++) { // configurable limit?
            permissions.add(new SecurityPermission("getProperty.security.provider." + i));
        }

        String s = Security.getProperty("securerandom.source");
        if ((s != null) && s.startsWith("file:/")) {
            permissions.add(new FilePermission(s.substring(5), "read"));
        }

        // should have been covered already but wasn't....
        permissions.add(new FilePermission("/dev/random", "read"));
      }

    /**
     * Add read-only permissions for everything on classpath.
     */
    public void addClassPathPermissions() {
        permissions.add(new FilePermission(String.format("%/lib/-",
            System.getProperty("java.home")), "read"));

        // add standard class path.
        String pathSep = System.getProperty("path.separator");
        for (String entry : System.getProperty("java.class.path").split(pathSep)) {
            File f = new File(entry);
            if (f.isFile()) {
                permissions.add(new FilePermission(entry, "read"));
            } else if (f.isDirectory()) {
                permissions.add(new FilePermission(String.format("%s/-", entry), "read"));
            } // or could be neither fish nor fowl
        }

        // add endorsed extensions.
        for (String dir : System.getProperty("java.ext.dirs").split(pathSep)) {
            permissions.add(new FilePermission(String.format("%s/-", dir), "read"));
        }
    }

    /**
     * Add other standard properties.
     */
    public void addOtherPropertyPermissions() {
        permissions.add(new PropertyPermission("jdbc.drivers", "read"));
        permissions.add(new PropertyPermission("java.security.egd", "read"));
        permissions.add(new PropertyPermission("socksProxyHost", "read"));
    }
}

有一点可怕.这些权限打开了大规模破坏的大门.

    // ------------ S C A R Y - B L O C K -----------
    permissions.add(new ReflectPermission("suppressAccessChecks"));  (!!)
    permissions.add(new RuntimePermission("createClassLoader")); (!!)
    permissions.add(new SecurityPermission("putProviderProperty.SUN"));
    permissions.add(new RuntimePermission("readFileDescriptor"));**
    permissions.add(new RuntimePermission("writeFileDescriptor"));
    // ------------ S C A R Y - B L O C K -----------

我还没有决定最好的行动方案.我认为我可以做的是覆盖checkPermission方法,并在看到前两个权限(至少)时查看调用堆栈.如果他们来自JDK深处,他们可能是安全的.如果来自用户代码,它们可能是不合适的.

上一篇:为什么在java中使用java.security.SecurityManager可以读取任何文件?


下一篇:Java策略文件 – 拒绝对代码库的权限