假设我sha1pass
用来在命令行上生成一些敏感密码的哈希值。我可以用它sha1pass mysecret
来生成一个哈希值,mysecret
但这具有mysecret
现在 bash 历史中的缺点。有没有办法完成这个命令的最终目标,同时避免mysecret
以纯文本形式显示,也许是通过使用passwd
-style 提示?
我也对将敏感数据传递给任何命令的通用方法感兴趣。当敏感数据作为参数(例如 in sha1pass
)或在 STDIN 上传递给某个命令时,该方法会发生变化。
有没有办法做到这一点?
编辑:这个问题引起了很多关注,下面提供了几个很好的答案。总结如下:
- 根据@Kusalananda 的回答,理想情况下,人们永远不必将密码或秘密作为命令行参数提供给实用程序。正如他所描述的,这在几个方面很容易受到攻击,应该使用设计更好的实用程序,该实用程序能够在 STDIN 上获取秘密输入
- @vfbsilva 的回答描述了如何防止将事物存储在 bash 历史记录中
- @Jonathan 的回答描述了一种非常好的方法来实现这一点,只要程序可以在 STDIN 上获取其秘密数据。因此,我决定接受这个答案。
sha1pass
在我的 OP 中只是一个例子,但讨论已经确定存在更好的工具来获取 STDIN 上的数据。 - 正如@R..在他的回答中指出的那样,对变量使用命令扩展是不安全的。
因此,总而言之,我接受了@Jonathan 的回答,因为它是最好的解决方案,因为您有一个设计良好且行为良好的程序可供使用。尽管将密码或机密作为命令行参数传递从根本上说是不安全的,但其他答案提供了减轻简单安全问题的方法。
理想情况下,您永远不要在命令行上键入明文密码作为命令的参数。这样做会使密码成为命令的参数,并且可以通过使用简单的工具(如
ps
或登录到某些审计日志)在进程表中看到命令行参数。话虽如此,肯定有一些方法可以从 shell 的命令历史记录中隐藏实际密码。
然后输入密码并按Enter。此处使用的
head
命令只接受一行输入,并且您键入的最后一个换行符不会是传递给的数据的一部分sha1pass
。为了防止字符回显:
该
stty -echo
命令关闭终端上键入字符的回显。然后用 恢复回声stty echo
。要传递标准输入,可以更改最后一个命令(如果
sha1pass
接受标准输入上的数据,您会这样做,但看起来好像这个特定实用程序忽略了它的标准输入):head
如果您需要多行cat
输入(上面假设应该传递单行,末尾没有换行符),然后somecommand
用Ctrl+D(如果您想在输入中包含换行符,则跟随Return,否则两次)。无论您使用什么外壳(只要它是类似 Bourne 或类似 rc 的外壳),这都会起作用。
如果命令前面有空格,则某些shell 可能不会将键入的命令保存在其历史文件中。这通常涉及必须设置
HISTCONTROL
为 valueignorespace
。至少OpenBSD 支持这一点,但不bash
支持,例如or 。用户可以使用选项或他们的变量来定义要忽略的模式。ksh
ksh93
dash
zsh
histignorespace
HISTORY_IGNORE
在支持读取
read
而不向终端回显字符的 shell 中,您也可以使用但这显然仍然存在相同的问题,可能会泄露进程表中的密码。
如果实用程序从标准输入读取,并且 shell 支持“here-strings”,则上面的内容可以更改为
评论摘要如下:
使用在命令行上给出的密码执行命令,上述所有命令都会执行此操作,除了将数据通过管道传输到命令的命令之外,可能会使同时运行的任何人都可以看到密码
ps
。但是,如果从交互式 shell 执行,上述命令都不会将输入的密码保存在 shell 的历史文件中。读取明文密码的行为良好的程序通过从其标准输入、文件或直接从终端读取来执行此操作。
sha1pass
确实需要命令行上的密码,直接输入或使用某种形式的命令替换。如果可能,请使用其他工具。
如果你
HISTCONTROL
这样设置:并以空格开始命令:
它不会存储在历史记录中。
如果使用
zsh
orbash
shell,请使用内置 shell 的 -s 选项read
从终端设备读取一行而不回显它。然后你可以使用一些花哨的重定向来使用变量作为标准输入。
如果有人跑
ps
,他们只会看到“sha1pass”。假设
sha1pass
在没有给出任何参数的情况下从标准输入读取密码(在一行上,忽略行分隔符)。通过管道或 here-doc 传递敏感数据:
或者:
将秘密放在(非导出的)shell 变量中很好,但您永远不能在命令行上使用这些变量,只能在此处文档和 shell 内部使用。
正如 Kusalananda 在评论中指出的那样,如果您在交互式 shell 中输入命令,您为 here 文档输入的行将存储在 shell 历史记录中,因此在那里输入密码是不安全的,但它仍然应该是安全地使用包含秘密的 shell 变量;历史将包含文本
$secret
,而不是任何$secret
扩展的内容。使用命令扩展并不安全:
因为输出将包含在命令行中并且在
ps
输出中可见(或从 /proc 手动读取),但在具有强化 /proc 的系统上除外。分配给变量也可以:
只需将值写入文件并传递文件:
我不确定它是如何
sha1pass
工作的,如果它可以将文件作为输入,你可以使用sha1pass < mysecret
. 如果没有,使用cat
可能是个问题,因为它包含最后的换行符。如果是这种情况,请使用(如果您head
支持-c
):如果 terdon 所做的事情是可能的,那么这是最好的解决方案,通过标准输入。剩下的唯一问题是他将密码写入磁盘。我们可以这样做:
就像 Kusalananda 所说,
stty -echo
确保您输入的内容在您stty echo
再次输入之前不会被看到。head -1
将从标准输入中获取一行并将其传递给sha1pass
.我会用
cat
将从 stdin 读取 untilEOF
,这可能是由按 Ctrl+D 引起的。然后,结果将作为参数传递给sha1pass
如果您要传递敏感信息并经常使用它,您可能最好对其进行加密。
把类似的东西
进入您的 .bashrc 将为您提供一个加密的环境变量,您可以在任何需要秘密的地方访问它,并且您将被提示输入您在创建环境变量时使用的密码短语/密码。
在上面的示例中,它是“秘密”
你访问它是一个命令如下
例如
对于您的查询,使用
sha1pass
. 您可以按如下方式创建和传递然后如下使用
base64 部分是为了让您可以设置变量
并且不会将您的秘密卡在命令历史记录等中。
当您生成密钥时,有时 base64 输出将包含多行,因此您需要为您的变量换行。
openssh 每次都会提示您输入密码以进行加密和解密,您可以在命令中提供一个密码,但是您只是在隐藏历史等内容。看看https://www.tecmint.com/ generate-encrypt-decrypt-random-passwords-in-linux/获取有关为此使用 openssh 的一些信息。https://www.serverlab.ca/tutorials/linux/administration-linux/how-to-base64-encode-and-decode-from-command-line/对于 base64 和https://stackoverflow.com/questions/16072351 /how-to-assign-an-output-to-a-shellscript-variable用于命令替换的不同选项我在上面使用了反勾号`