在 Windows 命令中使用密码参数安全吗?

问题描述 投票:0回答:3

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

> program.exe /password:secret

对于 Linux,最佳实践通常建议反对直接在命令行上指定密码,因为存在潜在的安全问题(密码可能出现在 shell 的历史文件和系统的进程表中):

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

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

但是,在四处搜索时,我没有看到针对 Windows 的同样有力的推荐。

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

这个问题的答案表明,专用的密码输入提示可以通过防止肩窥来提高安全性。是否有其他方法可以利用命令字符串中的可见密码来证明编写备用输入方法的合理性,无论是在 shell 上下文中还是在 Windows 管理进程的方式中?

从批处理文件或将密码作为参数传递给程序的 PowerShell 脚本启动程序时,安全隐患是否会发生变化?

$password = # prompt for password 
program.exe /password:$password

编辑 - 我知道我们可以将这个问题误解为基于意见,因为我提到“最佳实践”和“建议”来提供背景。然而,我寻求具体的证据来证明密码如何在命令参数中容易受到攻击,并且如果这个假设有效的话,我会寻找描述安全替代方案的具体示例或参考资料。

windows shell powershell security windows-scripting
3个回答
12
投票

Windows 历来不会在会话之间保存命令历史记录,仅在会话内保存。对于命令提示符和 PowerShell 来说都是如此。

正如 Bill Stewart 指出的那样,Windows 10 和 Windows 2016 上的 Windows PowerShell 默认包含 PSReadline,它确实会保存会话之间的命令历史记录。您可以通过查看此处的文件来看到这一点:

(Get-PSReadLineOption).HistorySavePath

但即使它设置为关闭,或者在不提供该选项的操作系统版本上,这并不意味着输入明文密码作为参数是一个好主意。

如果您必须提供这一点,您应该还可以有一种方法让程序在运行时提示。

对于 PowerShell 和其他 .Net 应用程序,接受明文密码会遇到另一个问题:它们会留在内存中,并且没有好的方法来显式清除它们。

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

这就是为什么

SecureString
存在,但并不是所有东西都可以使用它。

在 PowerShell 中,有一个

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

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

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

但在我看来,在这些情况下最好使用

PSCredential
对象,直到您需要纯文本版本为止。它有助于在内置/“官方”功能以及用户定义的命令中保持这种类型的标准化。

此类型也可以使用

Export-Clixml
轻松序列化为加密形式。 这可以为您提供一种非常好的方式,提供一个自动化选项来使用脚本中存储的凭据,无需任何明文内容,也无需提示或用户干预


10
投票

为了更直接地回答我的问题,这里对 briantist 的精彩回答做一个小补充:

当考虑到安全性时,不要输入或请求密码或其他敏感数据作为命令行参数。其他用户和程序可以相当简单地窥探命令行参数。

我们可以使用 Windows Management Instrumentation 在 PowerShell 中以及通过其他程序(例如基于 .NET 构建的程序)提取命令行参数。这是使用 PowerShell 的示例:

PS> Get-WmiObject Win32_Process -Filter 'Name = "program.exe"' | Select-Object CommandLine C:\program.exe /password:secret

对于同一系统上可以查看其他用户进程的任何用户,命令行密码参数也可以在任务管理器中看到:

Screenshot of Task Manager showing a plain-text password argument

正如 briantist 在他的回答中所写,我们编写的程序和脚本应该提供除命令行参数之外的输入敏感信息的替代方法。 PowerShell 脚本可以使用

PSCredential

SecureString
 对象在脚本之间安全地传递此信息。 


0
投票
在这个

thread中检查unclemeat的答案和TesselttingHeckler的评论

for /f "usebackq tokens=*" %%p in (`powershell -Command "$pword = read-host 'Enter Password' -AsSecureString ; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword); [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"`) do set password=%%p echo %password%
    
© www.soinside.com 2019 - 2024. All rights reserved.