如何使用PowerShell通过SSH传输安全密码?

时间:2018-01-25 00:58:31

标签: shell powershell security ssh windows-scripting

我正在编写在远程Windows机器上通过SSH执行命令或脚本的PowerShell模块,我正在寻找通过连接传输密码(或其他敏感信息)的方法。例如,假设我们有一个包含此调用的PowerShell脚本:

ssh user@host powershell -Command Invoke-Foo -Password $password

正如我从one of my previous questions获悉的那样,这个例子表明安全性很差 - 即使通过SSH加密,密码在两个系统上都显示为纯文本。为了防止这种情况,脚本将敏感数据存储为SecureStringPSCredential个对象:

$password = Read-Host -AsSecureString

...在本地计算机上运行正常,但脚本无法通过基于文本的SSH协议将SecureString对象传递给远程PowerShell进程。

对于后台:我正在自动化一些人在通过SSH连接到计算机时需要直接键入PowerShell会话的过程,因此之前不存在对此的需求。

不幸的是,我们已经使用PowerShell 4,因此新的PowerShell版本提供的SSH facilities不可用,并且由于非技术原因,我们无法使用基于WinRM的PowerShell远程处理正如我想的那样。这意味着我不能依赖New-PSSessionInvoke-Command来序列化并将本地对象发送到远程会话。

在这些限制条件下,如何设计PowerShell脚本以通过SSH将敏感数据作为文本传递,然后远程接收数据而不暴露它?有没有办法在不在每个系统上安装加密实用程序和密钥的情况下执行此操作?

1 个答案:

答案 0 :(得分:1)

由于您不能依赖集成的Windows身份验证,因此我不认为可以避免密钥管理。根据安全需求,SecureString如何?如果你可以容忍共同的秘密,那么可以移动它们。为了复制SecureStrings,必须使用预先生成的密钥。如果不是,Windows将通过DPAPI选择一个 - 该文件不能在其他系统上运行。

第一步是创建SecureString并将其保存到ConvertFrom-SecureString的文件中。内容用AES加以解析。

# Save the credential in a file
$PlainPassword = <mySecretPassword>
$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force

$key = (<pre-gernerate 24*8 bit values = 192 bits in an array. Keep it safe somewhere>)
$SecurePasswordKey = ConvertFrom-SecureString $SecurePassword -Key $key
set-content -path <myEncryptedFile> -input $SecurePasswordKey

现在Windows密码已加密,请将myEncryptedFile复制到远程服务器。无论如何都使用SSH,scp可以正常工作。

在SSH会话中使用远程服务器,根据加密文件创建PSCredential。

$key = (<Use the same pre-generated key here>)
$SecurePass = cat <myEncryptedFile>
$password = ConvertTo-SecureString -String $SecurePass -Key $key

$creds = new-object -typename System.Management.Automation.PSCredential `
  -argumentlist <domain\username>, $password

现在你有一个包含正确凭据的PSCredential对象,可以传递。

令人遗憾的是,移动$key是另一个问题。也许你可以容忍在一个文件中复制它,比如SecureString,并在调用所需的Powershell后删除它。如果,并且那是一个强大的if ,那么密钥只使用一次并且实际的凭证文件保密,您可以将密钥作为参数传递。

请注意,此解决方案可能包含多个安全漏洞。例如,如果您使用弱密钥并将文件复制到世界可读位置,则攻击者很容易解密密钥文件。