ソースコードなしでプログラムパラメータを隠す

ソースコードなしでプログラムパラメータを隠す

実行中のプログラムの一部の機密パラメータを非表示にする必要がありますが、ソースコードにアクセスできません。私も共有サーバーで実行していますが、hidepidsudo権限がないので、それはできません。

私が試したいくつかのことは次のとおりです。

  • export SECRET=[my arguments]、そして電話をかけたが./program $SECRET役に立たないようです。

  • ./program `cat secret.txt`私の主張はそこにありますが、secret.txt全能の神はps私の秘密を見つけることができます。

管理者の介入なしに私の主張を隠す他の方法はありますか?

答え1

説明どおりここ、Linuxはプログラムのパラメータをプログラムのデータスペースに入れ、その領域の先頭へのポインタを保持します。これはps、他の人がプログラムパラメータを見つけて表示するために使用する方法です。

データはプログラムスペースにあるため、これを操作できます。プログラム自体を変更せずにこれを行うには、main()プログラムの実際のメインルーチンの前に呼び出される関数を含むshimをロードする必要があります。このシムは実際のパラメータを新しいスペースにコピーし、psnull値のみが表示されるように元のパラメータを上書きします。

次のCコードはこれを行います。

/* https://unix.stackexchange.com/a/403918/119298
 * capture calls to a routine and replace with your code
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_main.so shim_main.c
 * LD_PRELOAD=/.../shim_main.so theprogram theargs...
 */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>

typedef int (*pfi)(int, char **, char **);
static pfi real_main;

/* copy argv to new location */
char **copyargs(int argc, char** argv){
    char **newargv = malloc((argc+1)*sizeof(*argv));
    char *from,*to;
    int i,len;

    for(i = 0; i<argc; i++){
        from = argv[i];
        len = strlen(from)+1;
        to = malloc(len);
        memcpy(to,from,len);
        memset(from,'\0',len);    /* zap old argv space */
        newargv[i] = to;
        argv[i] = 0;
    }
    newargv[argc] = 0;
    return newargv;
}

static int mymain(int argc, char** argv, char** env) {
    fprintf(stderr, "main argc %d\n", argc);
    return real_main(argc, copyargs(argc,argv), env);
}

int __libc_start_main(pfi main, int argc,
                      char **ubp_av, void (*init) (void),
                      void (*fini)(void),
                      void (*rtld_fini)(void), void (*stack_end)){
    static int (*real___libc_start_main)() = NULL;

    if (!real___libc_start_main) {
        char *error;
        real___libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
        if ((error = dlerror()) != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    real_main = main;
    return real___libc_start_main(mymain, argc, ubp_av, init, fini,
            rtld_fini, stack_end);
}

介入することはできませんが、mainを呼び出すmain()標準Cライブラリ関数を妨害する可能性があります。開始コメントに記載されているようにこのファイルをコンパイルし、指示に従って実行します。実際に呼び出されたことを確認できるようにコードを残しました。たとえば、次のようにします。__libc_start_mainshim_main.cprintf

LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100

その後、aを実行するとps空のコマンドとパラメータが表示されます。

コマンドパラメータが表示されるまでにはまだ時間がかかります。これを回避するには、shimを変更してファイルからシークレットを読み取り、プログラムに渡されたパラメータに追加できます。

答え2

  1. 関連アプリケーションのコマンドラインインターフェイスのドキュメントをお読みください。引数として直接提供するのではなく、ファイルに秘密を提供するオプションがある可能性が高いです。

  2. これが失敗した場合は、アプリケーションのセキュリティ秘密を提供するための安全な方法がないため、アプリケーションのバグレポートを送信してください。

  3. 常に慎重に(!)ソリューションを調整できます。ヤヨンの答えあなたの特定のニーズに応じて。特別な配慮スティーブンのコメントそしてそのフォローアップ。

答え3

hidepidプログラムが機能するために引数をプログラムに渡す必要がある場合は、procfsでそれを使用できない場合は何も運がありません。

これがbashスクリプトと呼ばれているので、bashはコンパイルされた言語ではないので、すでに利用可能なソースコードが必要です。

あなたがこれを行うことができない場合は、可能あるいは、同様のものを使用してプロセスのコマンドラインを再構築することができ、プロセスの開始後に/をgdb使用できますが、次のようになります。argcargv

  1. プログラムパラメータを変更する前に最初に公開されるため、これは安全ではありません。
  2. これはかなり古い学校なので、うまくいくことができるとしてもそれに頼ることはお勧めできません。

ソースコードを入手するか、ベンダーに連絡してコードを変更することをお勧めします。 POSIXオペレーティングシステムのコマンドラインで秘密を提供することは、セキュリティタスクと互換性がありません。

答え4

あなたができることは

 export SECRET=somesecretstuff

次に、あなたがCで書いていると仮定するか./program(または他の人がCで書いていて、それを変更または改善できると仮定して)、次のように使用します。環境のインポート(3)そのプログラムでは、おそらく

char* secret= getenv("SECRET");

その後、同じシェルで実行できますexport./programあるいは、環境変数名を渡すこともできます(実行./program --secret-var=SECRETなどを介して)。

ps秘密を明かさないだろうけど工程(5)それでも多くの情報を提供します(少なくとも同じユーザーの他のプロセスについて)。

また、見ることができますこれプログラムパラメータを渡すより良い方法を考案するのに役立ちます。

バラよりこの回答ワイルドカードとシェルの機能のより良い説明。

programおそらくデータを取得する他の方法があります。プロセス間通信一般プログラムの買収よりも合理的です(機密情報を扱う場合は必ずそうする必要があります)。その文書を読んでください。あるいは、プログラムを乱用する可能性があります(プログラムは秘密データを処理するためのものではありません)。

秘密のデータを隠すのは本当に難しいです。プログラムパラメータを介して渡すだけでは不十分です。

関連情報