Java安全管理器checkExec
我在Java安全管理器中实现安全检查时遇到了一个问题 我似乎误解了安全管理器中checkExec()方法的用途。我以为当我的应用程序试图通过命令行调用另一个Java应用程序时,它会被调用,但这似乎没有发生 下面是我想要实现的:使用我的自定义安全管理器的调用应用程序在命令行上执行“javasomeapp”。安全管理器检查这是否正常,并执行适当的操作 为了实现这一点,我做了以下工作:Java安全管理器checkExec,java,security,java-security,java-security-manager,rapid-prototyping,Java,Security,Java Security,Java Security Manager,Rapid Prototyping,我在Java安全管理器中实现安全检查时遇到了一个问题 我似乎误解了安全管理器中checkExec()方法的用途。我以为当我的应用程序试图通过命令行调用另一个Java应用程序时,它会被调用,但这似乎没有发生 下面是我想要实现的:使用我的自定义安全管理器的调用应用程序在命令行上执行“javasomeapp”。安全管理器检查这是否正常,并执行适当的操作 为了实现这一点,我做了以下工作: 创建了一个自定义安全管理器,该管理器覆盖checkExec方法。方法签名是public void checkExec
checkExec
方法。方法签名是public void checkExec(String cmd)
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
}
javainvokeme
JavaSomeApp
时,让安全管理器做一些事情)可能吗
谢谢你抽出时间
编辑:
下面是运行测试的一些代码和输出。这是一种快速原型样式,“拖到后面再清理”样式代码,所以不会很漂亮:
自定义安全管理器:
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.");
}
}
}
安全测试:
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());
}
}
}
调用者:
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()——没有控制台输出,我的文件系统中的任何地方都不存在verify.txt。(当然,我不确定执行这样的操作时安全管理器子类的行为应该是什么——所以这可能是正常的。如果是这样的话,我需要另一个快速而肮脏的方法来测试我是否遇到了某些代码行。)InvokeMeWasCalled.txt确实存在,因此,这一部分肯定是有效的。问题在于您的安全管理器被覆盖的
checkExec
。传递给checkExec
的cmd
参数只包含正在执行的命令中的第一个“单词”,因此在程序中,“java”是cmd
参数。因此,字符串不会以“java”开头,checkExec
不会执行if块,从而导致安全管理器执行“干净”检查
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
}
另外,作为旁注,修改后的命令执行将导致一个
StackOverflowerError
,因为只有第一个“单词”被传递给该方法。我知道代码并不漂亮,但它似乎使用了黑名单方法,即“如果我们认识到这是一个不需要的模式,那么我们抛出一个异常。”这对于现实世界来说不够健壮,而且它与实际问题有关(“cmd”不是指您认为它做了什么)
首先,在“if”块之后,如果我们不想做一些特殊的事情,应该有“else super.checkExec()”来运行常规处理。这就解决了您的问题。听起来您做得不错,而且您尝试做的是可能的,这让我相信这可能是代码问题。你能举个测试的例子吗?当然可以。我已经编辑了我的问题,包括相关的代码和测试输出。做了一些调试,我发现了问题;参考我贴出的答案。我学到了一些新东西
cmd
只是命令中空格前的第一个字符串。如果可以使用StringBuilder,请不要使用StringBuffer。几乎没有什么好的理由起诉StringBuffer。是的,这就是问题所在。这就解开了这个谜。我想如果我想强制我的程序使用某个安全管理器调用其他程序,我必须找到一种更聪明的方法来实现它。。。