Linux

如何隱藏作為命令行參數傳遞的密碼?

  • February 21, 2016

我正在執行一個軟體守護程序,它需要某些操作來輸入密碼來解鎖某些功能,例如:

$ darkcoind masternode start <mypassphrase>

現在我在無頭 debian 伺服器上遇到了一些安全問題。

每當我搜尋我的 bash 歷史記錄時,Ctrl+R我都可以看到這個超強密碼。現在我想我的伺服器被入侵了,一些入侵者可以訪問 shell,並且可以簡單地Ctrl+R在歷史記錄中找到我的密碼。

有沒有辦法在不顯示在 bash 歷史記錄ps/proc或其他任何地方的情況下輸入密碼片語?


更新 1:不向守護程序傳遞密碼會引發錯誤。這是沒有選擇的。


更新 2:不要告訴我刪除軟體或其他有用的提示,例如吊死開發人員。我知道這不是一個最佳實踐範例,但該軟體基於比特幣,所有基於比特幣的客戶端都是某種 json rpc 伺服器,它偵聽這些命令,其已知的安全問題仍在討論中(abc) .


更新 3:守護程序已經啟動並使用命令執行

$ darkcoind -daemon

執行ps僅顯示啟動命令。

$ ps aux | grep darkcoin
user     12337  0.0  0.0  10916  1084 pts/4    S+   09:19   0:00 grep darkcoin
user     21626  0.6  0.3 1849716 130292 ?      SLl  May02   6:48 darkcoind -daemon

因此,使用密碼傳遞命令不會出現ps或根本不會出現/proc

$ darkcoind masternode start <mypassphrase>
$ ps aux | grep darkcoin
user     12929  0.0  0.0  10916  1088 pts/4    S+   09:23   0:00 grep darkcoin
user     21626  0.6  0.3 1849716 130292 ?      SLl  May02   6:49 darkcoind -daemon

這就留下了一個問題,歷史在哪裡出現?僅在.bash_history?

真的,這應該在應用程序本身中修復。並且此類應用程序應該是開源的,因此在應用程序本身中解決問題應該是一種選擇。犯這種錯誤的安全相關應用程序也可能犯其他錯誤,所以我不相信它。

簡單的設置

但是您要求的是另一種方式,所以這裡有一個:

#define _GNU_SOURCE
#include <dlfcn.h>

int __libc_start_main(
   int (*main) (int, char * *, char * *),
   int argc, char * * ubp_av,
   void (*init) (void),
   void (*fini) (void),
   void (*rtld_fini) (void),
   void (* stack_end)
 )
{
 int (*next)(
   int (*main) (int, char * *, char * *),
   int argc, char * * ubp_av,
   void (*init) (void),
   void (*fini) (void),
   void (*rtld_fini) (void),
   void (* stack_end)
 ) = dlsym(RTLD_NEXT, "__libc_start_main");
 ubp_av[argc - 1] = "secret password";
 return next(main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}

編譯這個

gcc -O2 -fPIC -shared -o injectpassword.so injectpassword.c -ldl

然後執行你的過程

LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start fakepasshrase

main插入器庫將在執行應用程序的函式之前執行此程式碼。它將在對 main 的呼叫中用實際密碼替換最後一個命令行參數。但是,列印的命令行/proc/*/cmdline(因此被諸如 之類的工具看到ps)仍將包含 fake 參數。顯然,您必須使原始碼和從中編譯的庫僅對您自己可讀,因此最好在chmod 0700目錄中操作。而且由於密碼不是命令呼叫的一部分,因此您的 bash 歷史記錄也是安全的。

更高級的插入器

如果你想做更詳細的事情,你應該記住__libc_start_main在執行時庫被正確初始化之前執行。所以我建議避免任何函式呼叫,除非它們是絕對必要的。如果您希望能夠隨心所欲地呼叫函式,請確保在main完成所有初始化之後,在呼叫自身之前這樣做。對於以下範例,我必須感謝 Grubermensch,他指出瞭如何隱藏作為命令行參數傳遞的密碼,這引起getpass了我的注意。

#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>

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

static int my_main(int argc, char * * argv, char * * env) {
 char *pass = getpass(argv[argc - 1]);
 if (pass == NULL) return 1;
 argv[argc - 1] = pass;
 return real_main(argc, argv, env);
}

int __libc_start_main(
   int (*main) (int, char * *, char * *),
   int argc, char * * ubp_av,
   void (*init) (void),
   void (*fini) (void),
   void (*rtld_fini) (void),
   void (* stack_end)
 )
{
 int (*next)(
   int (*main) (int, char * *, char * *),
   int argc, char * * ubp_av,
   void (*init) (void),
   void (*fini) (void),
   void (*rtld_fini) (void),
   void (* stack_end)
 ) = dlsym(RTLD_NEXT, "__libc_start_main");
 real_main = main;
 return next(my_main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}

這會提示輸入密碼,因此您不再需要對插入器庫保密。佔位符參數被重用為密碼提示,所以像這樣呼叫它

LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start "Password: "

另一種選擇是從文件描述符(例如gpg --passphrase-fd)或從文件描述符中讀取密碼x11-ssh-askpass,或其他。

引用自:https://serverfault.com/questions/592744