假设我们有一个程序或脚本可以接受密码(或其他敏感信息)参数:

> program.exe /password:secret

对于Linux,最佳实践通常建议不要出于潜在的安全考虑而直接在命令行上指定密码(密码可以出现在shell的历史记录文件和系统的进程表中):

$ ./program.sh --password 'secret' &
[1] 4152

$ cat /proc/4152/cmdline
/bin/sh./program.sh--passwordsecret

但是,在四处搜索时,我没有看到针对Windows的同样强烈的建议。

在为Windows编写程序和脚本时,除了命令行选项的参数之外,我们是否应该提供一种替代方法来输入密码,以避免无意间泄露密码?

this question的答案表明,专用的密码输入提示可通过防止肩膀冲浪来提高安全性。还有其他方法可利用命令字符串中的可见密码来证明编写替代输入法的合理性,无论是在Shell上下文中还是Windows管理进程的方式中?

从批处理文件或将密码作为参数传递给程序的PowerShell脚本启动程序时,安全隐患是否会改变?
$password = # prompt for password
program.exe /password:$password

编辑-我了解我们会误解该问题为基于观点的问题,因为我提到了“最佳实践”和“建议”以提供背景知识。但是,我寻求具体证据来证明密码在命令自变量中可能是多么容易受到攻击,并且,如果此假设有效,则将具体描述安全替代方案的示例或引用。

最佳答案

Windows历史上不会在 session 之间保存命令历史记录,而仅在 session 中保存。对于命令提示符和PowerShell,都是如此。

正如Bill Stewart指出的那样,Windows 10和Windows 2016上的Windows PowerShell默认情况下包括PSReadline,它确实会保存 session 之间的命令历史记录。您可以通过在此处查看文件(Get-PSReadLineOption).HistorySavePath来看到它。

但是,即使已将其设置为关闭,或在未提供该选项的操作系统版本上,也并不意味着输入明文密码作为自变量是一个好主意。

如果必须提供,还应该有一种在运行时提示程序的方法。

对于PowerShell和其他.Net应用程序,您在接受纯文本密码时还有另一个问题:它们在内存中徘徊,并且没有明确清除它们的好方法。

这个问题有两个方面:.Net中的字符串是不可变的,这意味着您不能仅使用null或随机字符修改字符串以清除内存中的字符串(您实际上将创建一个全新的字符串),并且在此之上无法控制特定对象何时由垃圾回收处理,因此您不能显式删除它。

这就是 SecureString class存在的原因,但并非所有人都可以使用它。

在PowerShell中,有一个 PSCredential object,它以纯文本形式存储用户名,并以SecureString形式存储密码。它应该始终在PowerShell中使用,并且应该是首选的参数类型(代替单独的用户名和密码)。

PowerShell中大多数需要凭据的命令都将其视为此类对象。

您也可以使用此对象轻松检索密码的纯文本版本。这样做会将其放入托管字符串中,您会遇到上面提到的风险。

但是我认为,在这种情况下,最好还是使用PSCredential对象,直到需要纯文本版本为止。它有助于以内置/“官方”功能以及用户定义的命令来保持这种类型的标准化。

这种类型也可以通过 Export-Clixml 轻松序列化为加密形式。 This can give you a really nice way of providing an automated option to use stored credentials in scripts, with nothing in plaintext, and no prompting or user intervention required

08-06 00:44