导入凭据时,导入 Clixml 中是否有任何隐含的假设?



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

我想避免使用 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

您可以瞥一眼并建议是否有任何假设使代码不可靠吗?

您的方法仅适用于类Unix平台(macOS,Linux)上的PowerShell Core,但出于安全原因,它不应该在那里使用- 它不适用于Windows(无论是在Windows PowerShell中还是在PowerShell Core中),因为那里的密码 - 明智地 - 真正加密,而您的代码假设未加密的密码存储

安全警告

  • 类Unix平台上的[securestring]不提供任何保护 - 字符未加密存储 - Windows上的加密基础[securestring]依赖于仅限Windows的DPAPI(数据保护API)。

    • 对于新代码,通常不建议使用[securestring]- 请参阅此 Roslyn 分析器建议。
  • 如果您通过类Unix平台上的Export-CliXml[securestring]实例保存到文件中- 例如使用Get-Credential | Export-CliXml MyCredentials.xml- ">安全"数据(密码)可以被任何可以读取文件的人轻松检索。 相比之下,在 Windows 上存储了 DPAPI 加密的表示形式,该表示形式只能由同一台计算机上的同一用户解密。

    • 正如您的代码所演示的那样,在Unix上,持久化的[securestring]实例只是一个"字节字符串",其中包含构成纯文本内容的字符的Unicode代码点;例如,包含字符串'test'[securestring]持久化为'7400650073007400',可以构造如下:

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

      • 。并转换回来:
        [Text.Encoding]::Unicode.GetString([byte[]] ('7400650073007400' -split '(..)' -ne '' -replace '^', '0x'))

简而言之:在类Unix平台(PowerShellCore)上,不要使用Get-Credential | Export-CliXml来保存凭据- 它们将以未加密的方式存储。要提供任何保护,您必须通过文件权限拒绝其他人对文件的读取访问权限。


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

虽然此代码在技术上也适用于类Unix平台,但如上所述,它不提供任何保护。

请注意,它需要使用ConvertTo-SecureStringcmdlet 才能将 CLIXML 文件中的 DPAPI 加密密码表示形式转换为安全字符串([securestring]实例)。

# Load the CLIXML file into a [System.Xml.XmlDocument] ([xml]) instance.
($credXml = [xml]::new()).Load($PWD.ProviderPath + 'MyCredentials.xml')
# Take an XPath shortcut that avoids having to deal with namespaces.
# This should be safe, if you know your XML file to have been created with
#   Get-Credential | Export-CliXml MyCredentials.xml
$username, $encryptedPassword = 
$credXml.SelectNodes('//*[@N="UserName" or @N="Password"]').'#text'
$networkCred = [System.Net.NetworkCredential]::new(
$username, 
(ConvertTo-SecureString $encryptedPassword)
)
$networkCred.UserName
# $networkCred.Password  # CAUTION: This would echo the plain-text password.

相关内容

  • 没有找到相关文章

最新更新