有没有办法在 Java 中执行不安全的代码(禁用安全管理器)?

Posted

技术标签:

【中文标题】有没有办法在 Java 中执行不安全的代码(禁用安全管理器)?【英文标题】:Is there a way to execute unsafe code (disable security manager) in Java? 【发布时间】:2013-03-11 22:05:02 【问题描述】:

请不要发布“你不应该这样做”的答案。我不打算在生产代码中使用它,而只是为了一些黑客的乐趣。

在回答this question 时,我想运行一些任意不安全的Java 代码来取乐。有问题的代码只涉及查找 Java TreeMapleaf 节点。

运行下面的代码结果

Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.util

根据this question,我可以使用System.setSecurityManager(null) 来绕过大部分这些限制。但我不能这样做,因为加载我的类时会弹出错误。

我已经知道,在禁用安全管理器后,我可以使用反射来做所有我想做的事情。但这会使代码更难看。 核心 Java 开发人员如何编写他们的单元测试,例如,如果他们无法在 java.util 中打包东西?

我也尝试了-Djava.security.manager=...,但是当我将其设置为null 时,这会导致 JVM 初始化错误,而且我不确定我还能将其设置为什么。有什么想法吗?

package java.util;

import java.util.TreeMap.Entry;

public class TreeMapHax 

    static <K,V> List<Entry<K, V>> getLeafEntries(TreeMap<K, V> map)       
        Entry<K, V> root = map.getFirstEntry();
        while( root.parent != null ) root = root.parent;

        List<Entry<K,V>> l = new LinkedList<Entry<K,V>>();
        visitInOrderLeaves(root, l);
        return l;
    

    static <K,V> void visitInOrderLeaves(Entry<K, V> node, List<Entry<K, V>> accum)        
        if( node.left != null ) visitInOrderLeaves(node.left, accum);       
        if( node.left == null && node.right == null ) accum.add(node);      
        if( node.right != null ) visitInOrderLeaves(node.right, accum);
    

    public static void main(String[] args) 
        TreeMap<String, Integer> map = new TreeMap<String, Integer>();

        for( int i = 0; i < 10; i++ )
            map.put(Integer.toString(i), i);

        System.out.println(getLeafEntries(map));
    


【问题讨论】:

我猜核心开发人员要么乐于将他们的测试放在不同的包中(因为他们应该测试公共接口),要么有一个没有这些安全限制的 JVM 构建。毕竟,Oracle 是编写 JVM 代码的公司。 也许尝试获取源(冰茶或类似的东西),将您的文件偷偷放入“正确”的包中,然后编译整个东西?我不知道这是否可行,但它可能足以欺骗系统。这就是我要尝试的。 您可以使用引导类路径。创建您自己的 jar,其中包含 rt.jar 和此类中的所有内容。这是一个丑陋的黑客,但你说你确实想黑客。 【参考方案1】:

简单回答你的问题,没有通常的方法

java.* 中的类不受安全管理器的限制, 它们受到类加载器的限制。

做你想做的事,你需要找到一种方法来破解 jvm。 或者就像你提到的那样,通过反思来做。 或者只是在您自己的包中创建树图的副本(源克隆)。

【讨论】:

【参考方案2】:

如果您创建了一个自定义的java.lang.SecurityManager 并删除了所有安全逻辑,并将其编译到自定义 JVM 中,您应该能够通过将“java.security.manager”属性设置为自定义管理器来引用它.

由于Launcher 在您的程序启动之前读取该属性,因此您必须将自定义 SecurityManager 放在 JVM 认可的类路径中,而不是您自己的程序中(例如捆绑在核心 rt.jar 文件中)。

回答您关于核心开发人员如何处理此问题的问题:此类测试可能会针对自定义 JVM 运行,因为它们不遵守生产 JVM 的传统安全性。可以在here 找到此类存根的一个示例。

【讨论】:

【参考方案3】:

我认为您可以尝试为您的自定义 Java 包创建 jar 并将其放入 $JRE_HOME/lib/ext 并看到魔法!

【讨论】:

以上是关于有没有办法在 Java 中执行不安全的代码(禁用安全管理器)?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Java 中禁用短路评估?

什么是线程安全?

类型安全的 Javascript

仅为模拟器禁用应用程序传输安全性

Java: System.exit() 与安全策略

什么是线程安全,实现线程安全都有哪些方法