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

Cy *_*nol 5 security ssh shell powershell windows-scripting

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

ssh user@host powershell -Command Invoke-Foo -Password $password
Run Code Online (Sandbox Code Playgroud)

正如我从我之前的一个问题中了解到的那样,这个例子表明安全性很差——密码,即使通过 SSH 加密,在两个系统上都显示为纯文本。为了防止这种情况,脚本将敏感数据存储为SecureStringPSCredential对象:

$password = Read-Host -AsSecureString
Run Code Online (Sandbox Code Playgroud)

...在本地机器上运行良好,但脚本无法通过SecureString基于文本的 SSH 协议将对象传递到远程 PowerShell 进程。

对于背景:我正在自动化一些过程,人们需要在通过 SSH 连接到机器时直接输入到 PowerShell 会话中,因此以前不需要这样做。

不幸的是,我们受到 PowerShell 4 的限制,因此较新的 PowerShell 版本提供的SSH 工具不可用,而且由于非技术原因,我们无法使用基于 WinRM 的 PowerShell 远程处理,就像我想的那样. 这意味着我不能依赖New-PSSessionInvoke-Command序列化本地对象并将其发送到远程会话。

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

von*_*ryz 3

由于您不能依赖集成的 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
Run Code Online (Sandbox Code Playgroud)

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

在 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
Run Code Online (Sandbox Code Playgroud)

现在您有了一个包含正确凭据并且可以传递的 PSCredential 对象。

可悲的是,移动$key是另一个问题。也许您可以容忍将其复制到文件中,例如 SecureString,并在调用所需的任何 Powershell 后将其删除。如果(这是一个非常大的 if)密钥仅使用一次并且实际的凭证文件保密,那么您可以将密钥作为参数传递。

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