Shell

對於任何命令,有沒有辦法使用提示符在 bash 中傳遞敏感數據?

  • June 21, 2021

假設我sha1pass用來在命令行上生成一些敏感密碼的雜湊值。我可以用它sha1pass mysecret來生成一個雜湊值,mysecret但這具有mysecret現在 bash 歷史中的缺點。有沒有辦法完成這個命令的最終目標,同時避免mysecret以純文字形式顯示,也許是通過使用passwd-style 提示?

我也對將敏感數據傳遞給任何命令的通用方法感興趣。當敏感數據作為參數(例如 in sha1pass)或在 STDIN 上傳遞給某個命令時,該方法會發生變化。

有沒有辦法做到這一點?


編輯:這個問題引起了很多關注,下面提供了幾個很好的答案。總結如下:

  • 根據@Kusalananda 的回答,理想情況下,人們永遠不必將密碼或秘密作為命令行參數提供給實用程序。正如他所描述的,這在幾個方面很容易受到攻擊,應該使用設計更好的實用程序,該實用程序能夠在 STDIN 上獲取秘密輸入
  • @vfbsilva 的回答描述瞭如何防止將事物儲存在 bash 歷史記錄中
  • @Jonathan 的回答描述了一種非常好的方法來實現這一點,只要程序可以在 STDIN 上獲取其秘密數據。因此,我決定接受這個答案。sha1pass在我的 OP 中只是一個例子,但討論已經確定存在更好的工具來獲取 STDIN 上的數據。
  • 正如@R..在他的回答中指出的那樣,對變數使用命令擴展是不安全的。

因此,總而言之,我接受了@Jonathan 的回答,因為它是最好的解決方案,因為您有一個設計良好且表現良好的程序可以使用。儘管將密碼或機密作為命令行參數傳遞從根本上說是不安全的,但其他答案提供了減輕簡單安全問題的方法。

如果使用zshor bashshell,請使用內置 shell 的 -s 選項read從終端設備讀取一行而不回顯它。

IFS= read -rs VARIABLE < /dev/tty

然後你可以使用一些花哨的重定向來使用變數作為標準輸入。

sha1pass <<<"$VARIABLE"

如果有人跑ps,他們只會看到“sha1pass”。

假設sha1pass在沒有給出任何參數的情況下從標準輸入讀取密碼(在一行上,忽略行分隔符)。

理想情況下,您永遠不要在命令行上鍵入明文密碼作為命令的參數。這樣做會使密碼成為命令的參數,並且可以通過使用簡單的工具(如ps或登錄到某些審計日誌)在程序表中看到命令行參數。

話雖如此,肯定有一些方法可以從 shell 的命令歷史記錄中隱藏實際密碼。

sha1pass "$( head -n 1 )"

然後輸入密碼並按Enter。此處使用的head命令只接受一行輸入,並且您鍵入的最後一個換行符不會是傳遞給的數據的一部分sha1pass

為了防止字元回顯:

sha1pass "$( stty -echo; head -n 1; stty echo )"

stty -echo命令關閉終端上鍵入字元的回顯。然後用 恢復迴聲stty echo

要傳遞標準輸入,可以更改最後一個命令(如果sha1pass接受標準輸入上的數據,您會這樣做,但看起來好像這個特定實用程序忽略了它的標準輸入):

{ stty -echo; head -n 1; stty echo; } | somecommand

head如果您需要多行cat輸入(上面假設應該傳遞單行,末尾沒有換行符),然後somecommandCtrl+D(如果您想在輸入中包含換行符,則跟隨Return,否則兩次)。

無論您使用什麼外殼(只要它是類似 Bourne 或類似 rc 的外殼),這都會起作用。

如果命令前面有空格,則某些shell 可能不會將鍵入的命令保存在其歷史文件中。這通常涉及必須設置HISTCONTROL為 value ignorespace。至少OpenBSD 支持這一點,但不bash支持,例如or 。使用者可以使用選項或他們的變數來定義要忽略的模式。ksh``ksh93``dash``zsh``histignorespace``HISTORY_IGNORE

在支持讀取read而不向終端回顯字元的 shell 中,您也可以使用

IFS= read -rs password     # -s turns off echoing in bash or zsh
                          # -r for reading backslashes as-is,
                          # IFS= to preserve leading and trailing blanks
sha1pass "$password"

但這顯然仍然存在相同的問題,可能會洩露程序表中的密碼。

如果實用程序從標準輸入讀取,並且 shell 支持“here-strings”,則上面的內容可以更改為

IFS= read -rs password
somecommand <<<"$password"

評論摘要如下:

  • 使用在命令行上給出的密碼執行命令,上述所有命令都會執行此操作,除了將數據通過管道傳輸到命令的命令之外,可能會使同時執行的任何人都可以看到密碼ps。但是,如果從互動式 shell 執行,上述命令都不會將輸入的密碼保存在 shell 的歷史文件中。
  • 讀取明文密碼的行為良好的程序通過從其標準輸入、文件或直接從終端讀取來執行此操作。
  • sha1pass確實需要命令行上的密碼,直接輸入或使用某種形式的命令替換。
  • 如果可能,請使用其他工具。

引用自:https://unix.stackexchange.com/questions/439497