如何隱藏作為命令行參數傳遞的密碼?
我正在執行一個軟體守護程序,它需要某些操作來輸入密碼來解鎖某些功能,例如:
$ darkcoind masternode start <mypassphrase>
現在我在無頭 debian 伺服器上遇到了一些安全問題。
每當我搜尋我的 bash 歷史記錄時,
Ctrl+R
我都可以看到這個超強密碼。現在我想我的伺服器被入侵了,一些入侵者可以訪問 shell,並且可以簡單地Ctrl+R
在歷史記錄中找到我的密碼。有沒有辦法在不顯示在 bash 歷史記錄
ps
、/proc
或其他任何地方的情況下輸入密碼片語?更新 1:不向守護程序傳遞密碼會引發錯誤。這是沒有選擇的。
更新 2:不要告訴我刪除軟體或其他有用的提示,例如吊死開發人員。我知道這不是一個最佳實踐範例,但該軟體基於比特幣,所有基於比特幣的客戶端都是某種 json rpc 伺服器,它偵聽這些命令,其已知的安全問題仍在討論中(a、b、c) .
更新 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
,或其他。