通過Linux中的命令行參數將密鑰傳遞給openssl命令是否安全?我知道它刪除了實際的參數,所以它不能通過/ proc查看,但即使如此,是否有一些方法可以利用它?將密鑰材料傳遞給openssl命令
我有一個python應用程序,我想用OpenSSL通過stdin/stdout流在子進程中進行加密/描述,但我想知道我的密鑰是安全的。
通過Linux中的命令行參數將密鑰傳遞給openssl命令是否安全?我知道它刪除了實際的參數,所以它不能通過/ proc查看,但即使如此,是否有一些方法可以利用它?將密鑰材料傳遞給openssl命令
我有一個python應用程序,我想用OpenSSL通過stdin/stdout流在子進程中進行加密/描述,但我想知道我的密鑰是安全的。
在命令行上傳遞憑據不安全。這將導致您的密碼在系統的進程列表中可見 - 即使openssl儘快將其從進程列表中刪除,它也會立即出現。
openssl
爲您提供了一些方法來傳遞憑據 - 該手冊頁有一個名爲「PASS PHRASE ARGUMENTS」的部分,它記錄了您可以將憑證傳遞到openssl
的所有方式。我會解釋有關的:
ENV:VAR
讓您憑據傳遞中的環境變量。這比使用進程列表要好,因爲在Linux上,默認情況下,其他用戶無法讀取進程的環境 - 但在其他平臺上並不一定如此。
缺點是其他進程以相同的用戶身份運行,或者以root身份運行,將能夠通過/ proc輕鬆查看密碼。
這是很容易與Python的子使用:
new_env=copy.deepcopy(os.environ)
new_env["MY_PASSWORD_VAR"] = "my key data"
p = subprocess.Popen(["openssl",..., "-passin", "env:MY_PASSWORD_VAR"], env=new_env)
FD:數
這可以讓你告訴openssl
讀取從文件描述符,它將承擔憑據已經開放閱讀。利用這一點,你可以從你的過程中OpenSSL的直接寫入關鍵數據,像這樣的東西:
r, w = os.pipe()
p = subprocess.Popen(["openssl", ..., "-passin", "fd:%i" % r], preexec_fn=lambda:os.close(w))
os.write(w, "my key data\n")
os.close(w)
這將讓您的密碼在同一系統上的其他用戶提供安全,假設它們與登錄不同的帳戶。
通過上面的代碼,您可能會遇到os.write
呼叫阻塞的問題。如果openssl
在讀取密鑰之前等待其他事情發生,則可能發生這種情況。可以使用異步I/O(例如選擇循環)或使用額外的線程來處理write()close()。
這樣做的一個缺點是,如果您將closeFds=true
傳遞給subprocess.Popen,則它不起作用。子進程沒有辦法說「不關閉一個特定的fd」,所以如果你需要使用closeFds = true,那麼我建議使用file:
語法(下面)和命名管道。
文件路徑名:
不要使用此與實際的文件來存儲密碼!應該避免出於許多原因,例如您的程序可能會在清除該文件之前被殺死,並且對於大多數日誌文件系統來說,真正擦除磁盤上的數據幾乎是不可能的。
但是,如果與具有限制性權限的命名管道一起使用,這可能與使用上面的fd
選項一樣好。代碼來執行這將是類似於以前的片段,但你需要create a fifo而不是使用os.pipe()
:
pathToFifo = my_function_that_securely_makes_a_fifo()
p = subprocess.Popen(["openssl", ..., "-passin", "file:%s" % pathToFifo])
fifo = open(pathToFifo, 'w')
print >> fifo, "my key data"
fifo.close()
的這裏print
可以有相同的阻塞I/O問題,因爲上面的os.write
通話,決議也是一樣的。
不,它不安全。無論openssl在其開始運行後的命令行中做了什麼,仍然有一段時間可以在進程的命令行中看到這些信息:進程啓動後並且有機會null之前出來。
另外,事故發生的方式很多:例如,命令行在執行前由sudo記錄,或者在shell歷史記錄文件中結束。
Openssl支持大量傳遞敏感信息的方法,因此您無需在命令行中將其清除。從手冊頁:
通:密碼
實際的密碼是password。由於密碼對實用程序可見(如Unix下的「ps」),因此只能在安全性不重要的情況下使用此表單。
ENV:VAR
獲取環境變量var密碼。由於其他進程的環境在某些平臺上可見(例如某些Unix操作系統下的ps),因此應謹慎使用此選項。
文件路徑名:
路徑名的第一行是密碼。如果爲-passin和-passout參數提供了相同的路徑名參數,則第一行將用於輸入密碼,而下一行用於輸出密碼。路徑名不需要引用常規文件:例如它可以引用設備或命名管道。
FD:數
讀取文件描述符號的密碼。例如,這可以用於通過管道發送數據。
標準輸入
從標準輸入讀取密碼。
除前兩個選項外都很好。
不幸的是,我沒有尋找傳遞密碼的方式,而是一個實際的密鑰(-K命令行參數)。使用-pass不支持。但這至少證實了我懷疑命令行有風險。 – 2012-03-09 00:08:24
不幸的是,我沒有尋找方法來傳遞密碼,而是一個實際的鍵(-K命令行參數)。使用-pass不支持。但這至少證實了我懷疑命令行有風險。 – 2012-03-09 00:08:17
@TravisJensen非常感謝您接受!我假設你在這裏使用'openssl enc' - 手冊頁沒有給出'-K'的任何替代方法,所以你運氣不好。但是可能值得快速查看一下源代碼,如果有無證的替代方案,我不會感到驚訝。 – je4d 2012-03-09 00:16:17