gpt4 book ai didi

Java 安全管理器 checkExec

转载 作者:行者123 更新时间:2023-11-30 04:41:24 25 4
gpt4 key购买 nike

我在尝试在 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 时执行某些操作)可能吗?

感谢您的宝贵时间。

编辑:

以下是运行测试所产生的一些代码和输出。这是快速原型(prototype)风格,“先把它搞清楚,然后再清理”风格的代码,所以它不会很漂亮:

自定义安全管理器:

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() 正在被调用——没有控制台输出,并且 Verification.txt 在我的文件系统上的任何位置都不存在。 (当然,我不确定在执行这样的操作时安全管理器子类的行为应该是什么 - 所以也许这是正常的。如果是这样的话,我需要另一种快速而肮脏的方法来测试我是否正在执行某些代码行。)InvokeMeWasCalled.txt 确实存在,因此该部分肯定可以正常工作。

最佳答案

问题出在安全管理器的重写 checkExec 中。传递给 checkExeccmd 参数仅包含正在执行的命令中的第一个“单词”,因此在您的程序中,“java”是 cmd > 参数。因此,该字符串不会以“java”开头,并且 checkExec 不会执行 if block ,从而导致安全管理器进行“干净”检查。

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
}

此外,作为旁注,修改后的命令执行将导致 StackOverflowError,因为只有第一个“单词”被传递给该方法。

关于Java 安全管理器 checkExec,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12208002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com