- PR -

コマンドライン引数の隠蔽

投稿者投稿内容
らんぴーく
会議室デビュー日: 2005/04/07
投稿数: 9
投稿日時: 2008-06-17 21:46
Linux(RedHat)上で動くJavaアプリケーションなのですが、Shellスクリプトでユーザに情報を入力させた後アプリを起動します。
Shellにて起動後にPSコマンドで起動を確認すると、引数に与えたユーザの情報が見えてしまいます。

なんとか隠せないものかとググッたのですが、mysqlのクライアントはXで上書きしている…とか、Cでなら*argv[]を書き換えているとか…

なら、Javaならmain(String arg[])のarg[]を書き換えれば…と安直に思うのですが、そんなにうまくいかず。

どうもJavaのarg[]は、Cのargc, argv[]と同様の動きを期待してはいけない様子。

そこで、何とか引数を隠蔽する方法を教示願いたい次第です。


java -classpath [ライブラリのパス] [アプリのmain関数のあるクラス] "$引数1" "$引数2" "$引数3" "$引数4" "$引数5" "$引数6"
という起動です。
全引数を隠蔽したいです。

宜しくお願いします。
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2008-06-17 21:54
pure Javaでは不可能です。
コマンドラインではなく、標準入力から引数を読むように変更すればできそうですね。

echo "$引数1\n" "$引数2\n" ... | java -classpath ...
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2008-06-18 11:24
引数の難読化では、弱いですか、時間によってランダム化キーを変えるとか
わたなべ
大ベテラン
会議室デビュー日: 2007/12/09
投稿数: 123
お住まい・勤務地: 札幌
投稿日時: 2008-06-18 11:53
試していませんけど2段階で起動するのはいかがでしょうか?

つまり、mainのみを記述したダミーの起動クラスを作成し、そこに引数を与えます。
そのmainメソッドでは新しいプロセスとしてJavaを起動し、自分は終了します。

新しいプロセスに引数を渡すとそれが残るならば起動したプロセスに通信して渡すとか添付ファイル経由で渡すとか・・・
元のプロセスが動いている間は見えてしまいますが制限事項ですね

というか、コマンドライン引数が残ることに大きな問題があるんですか?
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-06-18 13:23
シェルを公開して、ユーザにプログラムを起動してもらうということですよね。
System.inを使って入力プロンプトを表示して、
その値を使ってもらうとか。
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2008-06-18 14:27
引用:

スクリプトプログラマさんの書き込み (2008-06-18 13:45) より:
環境変数で渡せば?



それがですねぇ、psにはコマンドの環境変数一覧を出す機能があるんですよ。

昔見た技に、psが出力できないくらい長い文字列を、第1引数にダミーで渡す、というのがありましたが、希望するレベルによってはこんな間に合わせでもよかったり。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2008-06-18 17:22
 わたなべさんの方法でちょっと作ってみました。
 Windowsなのでjps -mで確認してみたのですが、Testから復帰した後ならパラメタは見えないと思います。
 アプリで指定することのないパラメタを例えば-childとか-endとしてます。
 下のコードでは固定アプリしか呼べませんが、パラメタ化することで任意のクラスが呼べるようになると思います。

コード:
import java.io.*;
import java.util.*;

class Test {
    public Test() {}
    public static void main(String args[]) {
        try {
            if ((args.length==1) && args[0].equals("-child")) {
                // 子プロセスでアプリを呼び出す
                List<String> list = new ArrayList<String>();
                BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
                String line;
                while ((line=r.readLine())!=null) {
                    if (line.equals("-end")) {
                        String[] params = new String[list.size()];
                        params = list.toArray(params);
                        [アプリクラス].main(params);
                        System.exit(0);
                    }
                    else list.add(line);
                }
                System.exit(1);
            }
            else {
                // 起動プロセスでアプリを呼び出す子プロセスを起動し、すぐに終了
                List<String> commands = new ArrayList<String>();
                commands.add("java");
                commands.add("-cp");
                commands.add(System.getProperty("java.class.path"));
                commands.add("Test");
                commands.add("-child");
                ProcessBuilder pb = new ProcessBuilder(commands);
                Process pr = pb.start();
                PrintStream ps = new PrintStream(pr.getOutputStream());
                for (int i=0;i<args.length;i++) {
                    ps.println(args[i]);
                }
                ps.println("-end");
                ps.flush();
            }
        }
        catch (Exception e) {
e.printStackTrace();
        }
    }
}



らんぴーく
会議室デビュー日: 2005/04/07
投稿数: 9
投稿日時: 2008-06-18 18:30
皆さん、アドバイスありがとうございます。

わたなべさん、だっちょさんの方法が何となくアプリとしてよさそうなので
リーダーに相談してみたところ、「出来れば、今あるクラスを使ってほしい」とのこと。
クラス一覧やクラス図等の設計書を修正する余裕がないようです。

なので、今ある資源に対して修正をし、何とかPSコマンドで見せない…という方法としてスフレさんの方法でいこうかと思います(会議室違いを承知で伺いたいのですが、なぜ引数を囲む""の閉じの前に改行があるのでしょう??)

わたなべさん、だっちょさんの方法は後学のために、テスト環境用モジュールに組み込んでみて今後別件で需要があれば生かしたいと思います。

ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)