Powershell 5. 最小化内存时间的SecureString解密

Powershell 5. SecureString decryption that minimizes time in memory

我有一个使用 openssl.exe 查看私钥文件的脚本。然而,这个问题与对外部程序的任何调用有关。

通过 read-host -asSecureString 请求密码。

无法将 secureString 类型传递给 openssl.exe 命令。我需要将它解密为纯字符串,然后将该字符串传递给 openssl.exe

是否可以最大限度地减少字符串在内存中为纯文本的时间? 请注意,我们使用的是 Powershell 5。PS 7 个功能对我们不可用。

我看到的两种方法:

#Decrypt the secureString to a variable. 
#Create and remove that variable as soon as possible.
$securePass = Read-Host("Please enter a password") -asSecureString
$plainPass = [Net.NetworkCredential]::new('',$securePass).password
#Note there are many ways to perform the above step. If the 'Marshal method' is better, let me know.
./openssl.exe rsa -in user.key -passin pass:$plainpass
Remove-Variable $plainPass
#Decrypt the SecureString in the call to openssl. 
#Hope Powershell's garbage collection removes the String object as soon as the command is issued. 
$securePass = Read-Host("Please enter a password") -asSecureString
./openssl.exe rsa -in user.key -passin pass:$([Net.NetworkCredential]::new('',$securePass).password)
  1. 这些方法中的一种比另一种好吗?
  2. 考虑到脚本非常快,而且字符串永远不会写入文件,使用 secureString 是否也是一个问题?
  3. 无论它存在的时间有多短,我是否会通过使用字符串来破坏安全最佳实践?

既然你一直在提示,为什么不直接使用 Get-Credential 而不是 Read-Host?

$Creds = Get-Credential -Credential "$env:USERDOMAIN$env:USERNAME"
$Creds.UserName
$Creds.Password
$Creds.GetNetworkCredential().Password
# Results
<#
lab01\postanote
System.Security.SecureString
!SomeSuperSecretPassword1
#>

微软的做法:Working with Passwords, Secure Strings, and Credentials in Windows PowerShell

你应该经常清理自己。不要等系统来做。

这是我在 classes/workshops/engagements 我提供给其他人的建议方法。

# Collect all automatic and default loaded resources, put this at the top of your script
$AutomaticVariables                = Get-Variable
$AutomaticAndProfileLoadedVModules = Get-Module
$AutomaticLoadedFunctions          = Get-Command -CommandType Function

# Run this as the last items in your script
Function Clear-ResourceEnvironment
{
    [CmdletBinding(SupportsShouldProcess)]

    [Alias('cre')]

    Param
    (
        [switch]$AdminCredStore
    )

    # Clear instantiate reasource interop
    $null = [System.Runtime.InteropServices.Marshal]::
            ReleaseComObject([System.__ComObject]$Shell)

    # instantiate .Net garbage collection
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    # Clear all PSSessions
    Get-PSSession | 
    Remove-PSSession -ErrorAction SilentlyContinue

    # Clear static credential store, if switch is used
    If ($AdminCredStore)
    {Remove-Item -Path "$env:USERPROFILE\Documents\AdminCredSet.xml" -Force}
    Else
    {
        Write-Warning -Message "
        `n`t`tYou decided not to delete the custom Admin credential store.
        This store is only valid for this host and and user $env:USERNAME"
    }

    Write-Warning -Message "
    `n`t`tRemoving the displayed session specific variable and module objects"

    # Clear only variables created / used during the session
    Compare-Object -ReferenceObject (Get-Variable) -DifferenceObject $AutomaticVariables -Property Name -PassThru |
    Where -Property Name -ne 'AutomaticVariables' |
    Remove-Variable -Verbose -Force -Scope 'global' -ErrorAction SilentlyContinue
    Remove-Variable -Name AdminCredStore -Verbose -Force

    # Clear only modules loaded during the session
    Compare-Object -ReferenceObject (Get-Module) -DifferenceObject $AutomaticAndProfileLoadedVModules -Property Name -PassThru |
    Where -Property Name -ne 'AutomaticAndProfileLoadedVModules' |
    Remove-Module -Force -ErrorAction SilentlyContinue

    # Clear only functions loaded during the session
    Compare-Object -ReferenceObject (Get-Command -CommandType Function) -DifferenceObject $AutomaticLoadedFunctions  -Property Name -PassThru |
    Where -Property Name -ne 'AutomaticLoadedFunctions' |
    Remove-Item -Force -ErrorAction SilentlyContinue
}

注意事项:

当你使用解密到纯文本的那一刻,如果有人能嗅出你在做什么,那就是一个问题了。因此,这句格言,保护通道,保护数据,或两者都适用。

此外,如果有任何真实的日志记录(SEIM 工具、PowerShell 审计、抄本),无论您如何从 RAM 中清除它,它都会在日志中供所有人查看,除非您记得清除它条目。