导入凭据时,Import-Clixml中是否存在任何隐式假设?

时间:2019-04-21 12:46:19

标签: powershell credentials securestring networkcredentials powershell-core

我想知道是否有任何隐含的假设可能会使代码出现故障?

有一个原因我想避免使用Import-Clixml cmdlet? 因此,我开发了一种替代方法,即一系列命令,旨在从使用Export-Clixml创建的CliXml文件中提取用户名和密码。 现在它可以工作,但是我不确定例如拆分解决方案是否可靠。

$credFileUriBld = [UriBuilder]::New('file','localhost',-1,"MyCredentials.xml")) 

$credFile = [Xml.XMLDocument]::New()

$nsMgr4ps1xml = [Xml.XmlNamespaceManager]::New($credFile.NameTable)
$nsMgr4ps1xml.AddNamespace('ps1xml','http://schemas.microsoft.com/powershell/2004/04')
$credFile.Load($credFileUriBld.Path)

$netCredInfo = [System.Net.NetworkCredential]::New($credFile.SelectSingleNode('/ps1xml:Objs/ps1xml:Obj/ps1xml:Props/ps1xml:S[@N=''UserName'']/text()',$nsMgr4ps1xml).Get_Value(),
                                                   ($credFile.SelectSingleNode('/ps1xml:Objs/ps1xml:Obj/ps1xml:Props/ps1xml:SS[@N=''Password'']/text()',$nsMgr4ps1xml).Get_Value().Split('00') | 
                                                    ForEach-Object { if([String]::IsNullOrEmpty($_)) { } else { $_.Trim() } } |
                                                    ForEach-Object { [convert]::ToInt32($_,16) } |
                                                    ForEach-Object { [convert]::ToChar($_) } |
                                                    ForEach-Object -Begin { $ss=[SecureString]::New() } -Process {$ss.AppendChar($_)} -End { $ss }))

$netCredInfo.UserName
$netCredInfo.Password

您能否瞥一眼并告知是否存在使代码不可靠的假设?

1 个答案:

答案 0 :(得分:2)

您的方法<仅适用于 类Unix平台(macOS,Linux)上的PowerShell Core 中有效,但出于安全原因,不应在此处使用 -它在Windows上不起作用(在Windows PowerShell和PowerShell Core中均不起作用)。

安全警告

    在类似Unix的平台上,
  • [securestring]不提供保护-字符存储为未加密 -[securestring]基础的加密>仅在Windows上依赖于仅Windows的DPAPI

  • 如果您在类似Unix的平台上通过[securestring]Export-CliXml实例保存到文件 ,例如使用Get-Credential | Export-CliXml MyCredentials.xml-任何可以读取文件的人都可以轻松检索“安全”数据(密码)。相比之下,在Windows上,存储了DPAPI加密的表示,只能由同一用户在同一台​​计算机上解密。

    • 如您的代码所示,在Unix上,持久化的[securestring]实例只是一个“字节字符串”,其中包含构成纯文本的字符的Unicode代码点。内容;例如,包含字符串[securestring]的{​​{1}}被保留为'test',其构造如下:

      • '7400650073007400'

      • ...并转换为:
        -join [Text.Encoding]::Unicode.GetBytes('test').ForEach({ $_.Tostring('x2') })

简而言之:在类似Unix的平台(PowerShell Core )上,请勿使用[Text.Encoding]::Unicode.GetString([byte[]] ('7400650073007400' -split '(..)' -ne '' -replace '^', '0x'))来保存凭据-它们将被未加密地存储。要提供任何保护,您必须拒绝其他所有人通过文件权限对文件的读取访问权限。


仅在Windows上使用 ,如果您确实需要避免使用Import-CliXml,这是一个大大简化的解决方案也应该表现更好

尽管此代码在技术上 也可以在类似Unix的平台上运行,但如上所述,它没有任何保护作用。

请注意,它需要使用ConvertTo-SecureString cmdlet才能将CLIXML文件中的DPAPI加密的密码表示形式转换为安全字符串(Get-Credential | Export-CliXml实例)。 / p>

[securestring]