ConvertTo-SecureString 在不同的服务器上提供不同的体验 [英] ConvertTo-SecureString gives different experience on different servers

查看:68
本文介绍了ConvertTo-SecureString 在不同的服务器上提供不同的体验的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了从远程服务器上的 XML 文件创建凭据对象的问题.这是我用来测试的代码

XML 文件

<Obj RefId="0"><TN RefId="0"><T>Selected.System.Management.Automation.PSCredential</T><T>System.Management.Automation.PSCustomObject</T><T>System.Object</T></TN><MS><S N="用户名">域\用户名</S>< S N = 密码" > 01000000d08c9ddf0115d1118c7a00c04fc297eb010000001f19c6a42b9b0d48af2c531892e737ce000000000200000000001066000000010000200000006fb8862fbaea7b83cd2bcab35d7a8c8b4d71b7764c2a91d68eb3873864bc9d83000000000e8000000002000020000000fcbcc5552c3eb40ec337594f8286b08780709c1ac583d4679dcd7a3f5a92441b20000000c8e274811ed7a411b6741b2c65a67363f6aef380e684d13218d1ecc1281dfdb940000000c7279e81e21a1e57eed7da61e969f34fe2adf3d7e534bb5e10b89902adf4fdf20a69ec7e9b9e56dab512c789043a3b2cf0611e3b4893658b7c20f7892ce0ddfd</S></MS>

PowerShell 代码

 $cred = Import-Clixml "Payload\DeploymentCredential.xml"写主机 $cred$cred.Password = ConvertTo-SecureString $cred.Password写主机 $cred.Password$Credential = 新对象 System.Management.Automation.PsCredential($cred.UserName, $cred.Password)写主机 $Credential.GetNetworkCredential().password

在一台服务器(我的本地机器)上它工作得很好,但在远程服务器上,我收到这个错误

密钥在指定状态下无效.+ CategoryInfo : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException+ FullQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand

两者都具有相同版本的 PowerShell(3.0 Build -1 Revision -1),所以我不确定问题是什么.

解决方案

问题是原始凭证在导出到 xml 之前是如何创建的.

当您使用命令 ConvertTo-SecureString 时,它会使用您用户帐户下本地机器上的加密密钥对明文密码进行加密.这意味着如果您将其导出为 xml,则只能在该同一台本地机器上使用它.

当您将 xml 文件复制到另一台机器并尝试导入凭证对象时,它将无法工作,因为它将尝试使用不匹配的本地密钥对其进行解密.(因此出现错误消息).这是一项重要的安全措施,因为它可以防止我复制文件并在另一台计算机上使用它.

如果您需要在另一台计算机上拥有该用户帐户才能运行某些内容,则有两种选择:

  1. (最安全)在您需要的每台远程计算机上创建凭据对象.这样,它将使用本地加密密钥并防止人们窃取帐户.
  2. (最不安全)当您使用 ConvertTo-SecureString 创建凭证时,您可以指定 -Key-SecureKey 参数.这种方式不是使用本地加密密钥,而是使用您指定的密钥.然后在您的脚本中,您提供相同的密钥来解密它.这不太安全,因为我所要做的就是窃取凭据文件,然后查看您的脚本内部(以查看密钥),然后我就窃取了帐户.

--编辑--

以下是如何使用共享密钥的示例.它实际上只是在脚本中写入明文密码的一步,并且仅用于混淆密码.还有许多其他更好的方法可以在远程计算机上运行脚本,例如 PowerShell Remoting(参见:学习在 PowerShell 中使用远程处理).或者使用带有保存凭据的任务计划程序.

$PlainPassword = "P@ssw0rd"$SecurePassword = $PlainPassword |ConvertTo-SecureString -AsPlainText -Force$key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)$SecurePasswordKey = ConvertFrom-SecureString $SecurePassword -Key $key#输出哈希$SecurePasswordKey#输出76492d1116743f0423413b16050a5345MgB8ADIAKwBZAEkALwB0ADUAZwBQAHoAbwBNAEEAUwA0AFQAagB0AGsANwBmAHcAPQA9AHwAYgA3ADgAMwBjAGIANAAzADIAZAAwADEAYQA1AGUAMwBjAGUAYgA2AGMAMQBkADcAYQA3ADMAZAA1ADQAYwA0ADMAYgBlAGEANQAyAGQANQA0AGUAYgA5AGEAMgA0AGIANwBhAGIAMQAzADAAMwAzAGEANAA4ADEANQA0AGEAMAA =

在远程机器上:

<预> <代码> $ SecurePasswordKey = '76492d1116743f0423413b16050a5345MgB8ADIAKwBZAEkALwB0ADUAZwBQAHoAbwBNAEEAUwA0AFQAagB0AGsANwBmAHcAPQA9AHwAYgA3ADgAMwBjAGIANAAzADIAZAAwADEAYQA1AGUAMwBjAGUAYgA2AGMAMQBkADcAYQA3ADMAZAA1ADQAYwA0ADMAYgBlAGEANQAyAGQANQA0AGUAYgA5AGEAMgA0AGIANwBhAGIAMQAzADAAMwAzAGEANAA4ADEANQA0AGEAMAA ='$key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)$SecurePassword = ConvertTo-SecureString -String $SecurePasswordKey -Key $key

I am running into an issue creating a Credential Object from an XML File on a remote server. Here is the code I am using to test

XML File

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
     <TN RefId="0">
        <T>Selected.System.Management.Automation.PSCredential</T>
        <T>System.Management.Automation.PSCustomObject</T>
        <T>System.Object</T>
     </TN>
     <MS>
        <S N="UserName">domain\username</S>
        <S N="Password">01000000d08c9ddf0115d1118c7a00c04fc297eb010000001f19c6a42b9b0d48af2c531892e737ce000000000200000000001066000000010000200000006fb8862fbaea7b83cd2bcab35d7a8c8b4d71b7764c2a91d68eb3873864bc9d83000000000e8000000002000020000000fcbcc5552c3eb40ec337594f8286b08780709c1ac583d4679dcd7a3f5a92441b20000000c8e274811ed7a411b6741b2c65a67363f6aef380e684d13218d1ecc1281dfdb940000000c7279e81e21a1e57eed7da61e969f34fe2adf3d7e534bb5e10b89902adf4fdf20a69ec7e9b9e56dab512c789043a3b2cf0611e3b4893658b7c20f7892ce0ddfd</S>
</MS>

PowerShell Code

    $cred = Import-Clixml "Payload\DeploymentCredential.xml"
    write-host $cred
    $cred.Password = ConvertTo-SecureString $cred.Password 
    write-host $cred.Password
    $Credential = New-Object System.Management.Automation.PsCredential($cred.UserName, $cred.Password)
    write-host $Credential.GetNetworkCredential().password

On one server (my local machine) it works completely fine, but on the remote server, I get this error

Key not valid for use in specified state.    
+ CategoryInfo          : InvalidArgument: (:) [ConvertTo-SecureString], CryptographicException
+ FullyQualifiedErrorId : ImportSecureString_InvalidArgument_CryptographicError,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand

Both have the same version of PowerShell (3.0 Build -1 Revision -1), so I am not sure what the issue is.

解决方案

The issue is how the original credential is created before being exported to xml.

When you use the command ConvertTo-SecureString it encrypts the plaintext password with the encryption key on the local machine, under your user account. This means that if you export it to xml, you can only use it on that same local machine.

The minute you copy the xml file to another machine and try to import the credential object, it won't work because it will be trying to decrypt it with it's local keys which don't match. (hence the error message). This is an important security measure as it prevents me from copying the file and using it on another computer.

If you need to have the user account on another computer to run something, then there is two options:

  1. (Most secure) Create the credential object on each remote computer that you need it. This way it will use the local encryption keys and will prevent people from being able to steal the account.
  2. (Least secure) When you create the credential with ConvertTo-SecureString you can specify the -Key or -SecureKey parameter. This way instead of using the local encryption keys, it will use the one you specify. Then in your script, you provide the same key to decrypt it. This is less secure because all I have to do is steal the credential file, and take a look inside your script (to see the key) and then I have stolen the account.

--Edit--

Here is an example of how to use a shared key. It is literally only one step up from writing in a plaintext password in your script, and is only used to obfuscate the password. There are many other -better- ways of running scripts on remote machines like PowerShell Remoting (See: Learn to Use Remoting in PowerShell). Or using Task Scheduler with saved credentials.

$PlainPassword = "P@ssw0rd"
$SecurePassword = $PlainPassword | ConvertTo-SecureString -AsPlainText -Force

$key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)

$SecurePasswordKey = ConvertFrom-SecureString $SecurePassword -Key $key

#Output the hash
$SecurePasswordKey

#Output
76492d1116743f0423413b16050a5345MgB8ADIAKwBZAEkALwB0ADUAZwBQAHoAbwBNAEEAUwA0AFQAagB0AGsANwBmAHcAPQA9AHwAYgA3ADgAMwBjAGIANAAzADIAZAAwADEAYQA1AGUAMwBjAGUAYgA2AGMAMQBkADcAYQA3ADMAZAA1ADQAYwA0ADMAYgBlAGEANQAyAGQANQA0AGUAYgA5AGEAMgA0AGIANwBhAGIAMQAzADAAMwAzAGEANAA4ADEANQA0AGEAMAA=

On remote machine:

$SecurePasswordKey = '76492d1116743f0423413b16050a5345MgB8ADIAKwBZAEkALwB0ADUAZwBQAHoAbwBNAEEAUwA0AFQAagB0AGsANwBmAHcAPQA9AHwAYgA3ADgAMwBjAGIANAAzADIAZAAwADEAYQA1AGUAMwBjAGUAYgA2AGMAMQBkADcAYQA3ADMAZAA1ADQAYwA0ADMAYgBlAGEANQAyAGQANQA0AGUAYgA5AGEAMgA0AGIANwBhAGIAMQAzADAAMwAzAGEANAA4ADEANQA0AGEAMAA='

$key = (3,4,2,3,56,34,254,222,1,1,2,23,42,54,33,233,1,34,2,7,6,5,35,43)

$SecurePassword = ConvertTo-SecureString -String $SecurePasswordKey -Key $key

这篇关于ConvertTo-SecureString 在不同的服务器上提供不同的体验的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆