1

JavaSecurityManagerでセキュリティチェックを実装しようとして問題が発生しました。

セキュリティマネージャのcheckExec()メソッドの目的を誤解しているようです。アプリケーションがコマンドラインから別のJavaアプリケーションを呼び出そうとすると呼び出されると思いましたが、そうではないようです。

これが私がしたいことです:私のカスタムセキュリティマネージャーを使用する呼び出しアプリケーションは、コマンドラインで「javaSomeApp」を実行します。セキュリティマネージャは、これで問題がないかどうかを確認し、適切なアクションを実行します。

これを達成するために、私は次のことを行いました。

  1. checkExecメソッドをオーバーライドするカスタムセキュリティマネージャーを作成しました。メソッドシグネチャはpublic void checkExec(String cmd)です。

  2. テストクラスSecurityTestを作成しました。

  3. SecurityTestは、カスタムセキュリティマネージャーをセキュリティマネージャーとして割り当てます。

  4. 次に、SecurityTestjava 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が存在するため、その部分は確実に機能しています。

4

2 に答える 2

2

問題は、セキュリティマネージャのオーバーライドにありますcheckExeccmdに渡されるパラメータにはcheckExec、実行中のコマンドの最初の「単語」のみが含まれているため、プログラムでは「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
}

また、補足として、変更されたコマンドの実行はStackOverflowError、最初の「単語」のみがメソッドに渡されるために発生します。

于 2012-08-31T03:33:38.997 に答える
0

コードがきれいであることを意図していないことは知っていますが、ブラックリストアプローチを使用しているようです。つまり、「これが不要なパターンであると認識した場合は、例外をスローします」。これは現実の世界では十分に堅牢ではなく、実際の問題に関連しています(「cmd」はあなたが思ったことを意味しません)。

手始めに、「if」ブロックの後に、特別なことをしたくない場合に通常の処理を実行するための「elsesuper.checkExec()」が必要です。それはあなたの問題をすぐそこに拾い上げたでしょう。

于 2015-02-12T01:36:16.260 に答える