Java安全管理器checkExec

时间:2012-08-31 02:02:04

标签: java security java-security java-security-manager

我在尝试在Java安全管理器中实现安全检查时遇到问题。

我似乎误解了安全管理器中checkExec()方法的用途。我认为当我的应用程序试图通过命令行调用另一个Java应用程序时会调用它,但这似乎不会发生。

以下是我想要发生的事情:使用我的自定义安全管理器的调用应用程序在命令行上执行“java SomeApp”。安全管理器检查这是否正常并执行适当的操作。

为了尝试实现这一目标,我做了以下事情:

1)创建了一个自定义安全管理器,它覆盖了checkExec方法。方法签名是“public void checkExec(String cmd)”。

2)创建了一个测试类SecurityTest。

3)SecurityTest将我的自定义安全管理器指定为其安全管理器。

4)SecurityTest然后在命令行上运行“java InvokeMe”。

5)自定义安全管理器拦截此操作并执行某些操作。

1到4很好,但5从未发生过。我已经验证我的自定义安全管理器是有效的,它已成功分配给SecurityTest,SecurityTest成功运行InvokeMe。但是,我能够辨别出自定义安全管理器中的checkExec()方法。

我哪里错了?我正在尝试做什么(让安全管理器在应用程序调用“Java SomeApp”时做某事)甚至可能吗?

感谢您的时间。

修改

以下是运行测试所产生的一些代码和输出。这是一种快速原型风格,“将其打开并清理后来”的样式代码,因此它不会很漂亮:

自定义安全管理器:

import java.util.*;
import java.io.*;
class DTESecurityManager extends SecurityManager {
    // instance variables

    DTESecurityManager() {
        super();
        //assign a bunch of variables
        System.out.println("TEST 1");
    }

    public void checkExec(String cmd) {
        if (cmd.toLowerCase().startsWith("java ")) {
            if (cmd.matches("(?i).*-djava.security.manager.*")) {
                throw new SecurityException("Cannot assign a security manager to invoked Java applications.");
            }
            StringBuffer intermediateCommand = new StringBuffer(cmd).insert(5, "-Djava.security.manager=DTESecurityManager ");
            String modifiedCommand = new String(intermediateCommand);
            try {
                Runtime rt = Runtime.getRuntime();
                Process pr = rt.exec(modifiedCommand);
            } catch (Exception e) {
                System.err.println("Error: " + e.getMessage());
            }
            try {
                FileWriter fstream = new FileWriter("Verification.txt");
                BufferedWriter out= new BufferedWriter(fstream);
                out.write("I worked.");
                out.close();
            } catch (Exception e) {
                System.err.println("Error: " + e.getMessage());
            }
            throw new SecurityException("Command was executed, but was modified to force invoked application to use this security manager.");
        }
    }
}

SecurityTest:

import java.io.*;

class SecurityTest {

    public static void main(String[] args) {
        try {
            System.setSecurityManager(new DTESecurityManager());
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
        try {
            System.out.println("If we got this far, we had no problems setting our security manager.");
            System.out.println("Now let's try to invoke another Java application.");
            Runtime rt = Runtime.getRuntime();
            Process pr = rt.exec("java InvokeMe");
            System.out.println("I reached the end of my test without crashing. Now terminating.");
        } catch (Exception e) {
            System.out.println("Exception message: " + e.getMessage());
        }
    }

}

InvokeMe:

import java.io.*;

class InvokeMe {

    public static void main(String[] args) {
        System.out.println("I, InvokeMe, have been invoked successfully.");
        try {
        FileWriter fstream = new FileWriter("InvokeMeWasCalled.txt");
            BufferedWriter out= new BufferedWriter(fstream);
            out.write("It worked.");
            out.close();
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }
    }

}

测试输出:

TEST 1
If we got this far, we had no problems setting our security manager.
Now let's try to invoke another Java application.
I reached the end of my test without crashing. Now terminating.

没有迹象表明checkExec()被调用 - 没有控制台输出,Verification.txt在我的文件系统的任何地方都不存在。 (当然,在执行这样的操作时,我不确定安全管理器子类的行为应该是什么 - 所以也许这是正常的。如果是这样的话,我需要另一种快速而肮脏的方法来测试我是否“我遇到了某些代码行。”InvokeMeWasCalled.txt确实存在,因此该部分肯定有效。

2 个答案:

答案 0 :(得分:2)

问题出在您的安全管理员的覆盖checkExec中。传递给cmd的{​​{1}}参数仅包含正在执行的命令中的第一个“单词”,因此在您的程序中,“java”是checkExec参数。因此,字符串不以“java”开头,cmd不执行if块,导致安全管理器进行“干净”检查。

checkExec

另外,作为旁注,修改后的命令执行将导致public void checkExec(String cmd) { System.out.println(cmd); // prints "java" if (cmd.toLowerCase().startsWith("java ") { ... } // is false // no security exception is thrown, allowing your command } ,因为只有第一个“单词”被传递给方法。

答案 1 :(得分:0)

我知道代码不是很漂亮,但似乎是使用黑名单方法,即"如果我们认识到这是一个不需要的模式,那么我们抛出异常。&# 34;这对现实世界来说还不够强大,而且它与实际问题有关(' cmd'并不意味着你的想法)。

对于初学者来说,在' if'之后块,应该有'否则super.checkExec()'如果我们不想做一些特别的事情,可以进行常规处理。那会在那里找到你的问题。