Существуют ли неявные предположения в Import-Clixml при импорте учетных данных? - PullRequest
2 голосов
/ 21 апреля 2019

Интересно, есть ли какие-то неявные предположения, которые я принял, которые могут сделать код неисправным?

Есть причина, по которой я хочу избегать использования командлета Import-Clixml?Поэтому я разработал альтернативу, то есть последовательность команд, которая предназначена для извлечения имени пользователя и пароля из файла CliXml, созданного с помощью Export-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 Ответ

2 голосов
/ 22 апреля 2019

Ваш подход только работает в PowerShell Core на Unix-подобных платформах (macOS, Linux), но он не должен использовать его в целях безопасности - он не работает в Windows (ни в Windows PowerShell, ни в PowerShell Core).

Предупреждение безопасности :

  • [securestring] на Unix-подобных платформах НЕТ защиты - символы хранятся в незашифрованном виде - шифрование, лежащее в основе [securestring] только в Windows полагается только на Windows DPAPI .

  • Если вы сохраните экземпляр [securestring] в файле через Export-CliXml на Unix-подобной платформе - например, с помощью Get-Credential | Export-CliXml MyCredentials.xml - «безопасные» данные (пароль) могут быть легко извлечены любым, кто может прочитать файл . Напротив, в Windows хранится представление с шифрованием DPAPI, которое может быть дешифровано только одним и тем же пользователем на одном компьютере.

    • Как показывает ваш код, в Unix постоянный экземпляр [securestring] представляет собой просто "байтовую строку", которая содержит кодовые точки Unicode символов, составляющих содержимое простого текста ; например, [securestring], содержащая строку 'test', сохраняется как '7400650073007400', что можно построить следующим образом:

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

      • ... и преобразован обратно с:
        [Text.Encoding]::Unicode.GetString([byte[]] ('7400650073007400' -split '(..)' -ne '' -replace '^', '0x'))

Вкратце: На Unix-подобных платформах (PowerShell Core ) НЕ используйте Get-Credential | Export-CliXml для сохранения учетных данных - они будут храниться в незашифрованном виде. Чтобы обеспечить какую-либо защиту, вам нужно будет запретить всем остальным доступ на чтение к файлу с помощью прав доступа к файлу .


Для использования только для Windows , если вам нужно избегать Import-CliXml, вот значительно упрощенное решение , что также должен работать лучше .

Хотя этот код технически также работает на Unix-подобных платформах, он не обеспечивает никакой защиты, как обсуждалось выше.

Обратите внимание, что требуется преобразование командлета DPAPI , зашифрованного в файле CLIXML, в защищенную строку ([securestring]) с помощью командлета ConvertTo-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 = [pscredential]::new(
  $username, 
  (ConvertTo-SecureString $encryptedPassword)
).GetNetworkCredential()

$networkCred.UserName
# $networkCred.Password  # CAUTION: This would echo the plain-text password.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...