2012-03-08 64 views
2

通過Linux中的命令行參數將密鑰傳遞給openssl命令是否安全?我知道它刪除了實際的參數,所以它不能通過/ proc查看,但即使如此,是否有一些方法可以利用它?將密鑰材料傳遞給openssl命令

我有一個python應用程序,我想用OpenSSL通過stdin/stdout流在子進程中進行加密/描述,但我想知道我的密鑰是安全的。

回答

2

在命令行上傳遞憑據不安全。這將導致您的密碼在系統的進程列表中可見 - 即使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通話,決議也是一樣的。

+0

不幸的是,我沒有尋找方法來傳遞密碼,而是一個實際的鍵(-K命令行參數)。使用-pass不支持。但這至少證實了我懷疑命令行有風險。 – 2012-03-09 00:08:17

+0

@TravisJensen非常感謝您接受!我假設你在這裏使用'openssl enc' - 手冊頁沒有給出'-K'的任何替代方法,所以你運氣不好。但是可能值得快速查看一下源代碼,如果有無證的替代方案,我不會感到驚訝。 – je4d 2012-03-09 00:16:17

2

不,它不安全。無論openssl在其開始運行後的命令行中做了什麼,仍然有一段時間可以在進程的命令行中看到這些信息:進程啓動後並且有機會null之前出來。

另外,事故發生的方式很多:例如,命令行在執行前由sudo記錄,或者在shell歷史記錄文件中結束。

Openssl支持大量傳遞敏感信息的方法,因此您無需在命令行中將其清除。從手冊頁:

  • 通:密碼

    實際的密碼是password。由於密碼對實用程序可見(如Unix下的「ps」),因此只能在安全性不重要的情況下使用此表單。

  • ENV:VAR

    獲取環境變量var密碼。由於其他進程的環境在某些平臺上可見(例如某些Unix操作系統下的ps),因此應謹慎使用此選項。

  • 文件路徑名:

    路徑名的第一行是密碼。如果爲-passin和-passout參數提供了相同的路徑名參數,則第一行將用於輸入密碼,而下一行用於輸出密碼。路徑名不需要引用常規文件:例如它可以引用設備或命名管道。

  • FD:數

    讀取文件描述符號的密碼。例如,這可以用於通過管道發送數據。

  • 標準輸入

    從標準輸入讀取密碼。

除前兩個選項外都很好。

+0

不幸的是,我沒有尋找傳遞密碼的方式,而是一個實際的密鑰(-K命令行參數)。使用-pass不支持。但這至少證實了我懷疑命令行有風險。 – 2012-03-09 00:08:24