Quantcast
Channel: Windows PowerShell forum
Viewing all articles
Browse latest Browse all 21975

Data Protection in PSSession - Access is denied

$
0
0

Hi,

I have a Windows service that is written in Python which runs under a local administrator account.  Under various conditions it creates a New-PSSession to the local computer as another user (e.g. administrator) and exports a PSCredential for the same account.  However until Internet Explorer has been run as administrator the export fails with "access is denied".  The system is Windows 2012 R2.

I assume that there is simply something which isn't being initialised until after IE has been run but I am unable to work out what this is or how it might be replicated in the powershell script.  After a reboot the system returns to the initial non-working state.

Before IE:

PS C:\sbin> C:\sbin\CredentialWriter.ps1 -Path C:\tmp\test.xml -ForUser .\Administrator -ForPw TheAdminPassword


Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
70     Job70           RemoteJob       Completed     True            localhost            ...                      
Exception calling "Protect" with "3" argument(s): "Access is denied.
" Access is denied.



Exception calling "Protect" with "3" argument(s): "Access is denied.
"
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : CryptographicException
    + PSComputerName        : localhost
 
Access is denied.
    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-SecureString], CryptographicException
    + FullyQualifiedErrorId : System.Security.Cryptography.CryptographicException,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand
    + PSComputerName        : localhost

After IE:

PS C:\sbin> C:\sbin\CredentialWriter.ps1 -Path C:\tmp\test.xml -ForUser .\Administrator -ForPw TheAdminPassword


Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
72     Job72           RemoteJob       Completed     True            localhost            ...                      



01000000d08c9ddf0115....

The script:

<#
.SYNOPSIS
    Create a PSCredential file for a user account.
.DESCRIPTION
    This is a script which can create a PSCredential file for any local account.  It can optionally write
    the credentials out for consumption by another user account account.
.PARAMETER Path
    The file which will be created containing the PSCredential.
.PARAMETER ForUser
    The username which the PSCredential is being created for.
.PARAMETER ForPw
    The password for ForUser which will be encoded.
.PARAMETER AsUser
    Write the credential out for use by this user.
.PARAMETER AsPw
    The password the AsUser account.
.PARAMETER Help
    Get help with this command.
.EXAMPLE
    CredWriter -Path "C:\a\path\creds.xml" -ForUser ".\Administrator" -ForPw "AdminP4S$w0rd"

    This will write the ForUser credential to C:\a\path\creds.xml which can be subsequently used by
    the same user to automatically execute commands.
.EXAMPLE
    CredWriter -Path "C:\a\path\creds.xml" -ForUser ".\Administrator" -ForPw "AdminP4S$w0rd" -AsUser ".\UnprivilegedUser" -AsPw "UnprivPw"

    This will write the ForUser credential to C:\a\path\creds.xml which can subsequently be used byt the UnprivilegedUser to run
    a command with the ForUser account.  WARNING: There are no restrictions on what commands the credential file could be used
    to execute once it is given to the untrusted user.
#>

[CmdletBinding(DefaultParameterSetName="HelpOnly")]
param(
        [Parameter(ParameterSetName="ForAccount",Mandatory=$true)]
        [Parameter(ParameterSetName="AsAccount",Mandatory=$true)]
                [string]$Path,

        [Parameter(ParameterSetName="ForAccount",Mandatory=$true)]
        [Parameter(ParameterSetName="AsAccount",Mandatory=$true)]
                [string]$ForUser,

        [Parameter(ParameterSetName="ForAccount",Mandatory=$true)]
        [Parameter(ParameterSetName="AsAccount",Mandatory=$true)]
                [string]$ForPw,

        [Parameter(ParameterSetName="AsAccount",Mandatory=$true)]
                [string]$AsUser,

        [Parameter(ParameterSetName="AsAccount",Mandatory=$true)]
                [string]$AsPw,

        [Parameter(ParameterSetName="HelpOnly",Mandatory=$false)]
        [Parameter(ParameterSetName="ForAccount",Mandatory=$false)]
        [Parameter(ParameterSetName="AsAccount",Mandatory=$false)]
                [switch]$Help
)

# print help if requested
if($help -or ($PSCmdlet.ParameterSetName -eq "HelpOnly")) {
        Get-Help $myInvocation.MyCommand.Path
        exit
}

# If no AsUser account given then write credentials as ForUser.
if(!$AsUser) {
        $AsUser = $ForUser
        $AsPw = $ForPw
}

$EAsPw = ConvertTo-SecureString -String $AsPw -AsPlainText -Force
$AsCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AsUser, $EAsPw

try {
        # Executing as a job in the current session fails as it seems that there is a restriction on
        # executing the command with a nother user credential when invoked from a service.  At the console
        # command line there is no problem
        #$job = Start-Job -InitializationScript ([ScriptBlock]::Create("Set-Location C:\sbin")) -Credential $AsCred -ScriptBlock {
        # As an alternate method we create a new powershell session to the local computer and issues commands
        # through this.
        $s = New-PSSession -EnableNetworkAccess -Credential $AsCred -ErrorAction Stop
        $job = Invoke-Command -AsJob -Session $s -ScriptBlock {
                [CmdletBinding()]
                param(
                        [Parameter(Mandatory=$true)][string]$Path,
                        [Parameter(Mandatory=$true)][string]$ForUser,
                        [Parameter(Mandatory=$true)][string]$ForPw
                )

        Add-Type -Assembly System.Security

        # This always works
                #$x = [System.Security.Cryptography.ProtectedData]::Protect( "fff".tochararray(), $null, [System.Security.Cryptography.DataProtectionScope]::LocalMachine);
        # Only works after IE executed under -ForUser
                $x = [System.Security.Cryptography.ProtectedData]::Protect( "fff".tochararray(), $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser);

                $EForPw = ConvertTo-SecureString -String $ForPw -AsPlainText -Force
                Write-Host ($EForPw | ConvertFrom-SecureString)
        } -ArgumentList $Path, $ForUser, $ForPw
        Wait-Job -Job $job
        Write-Host ($job.ChildJobs[0].Error)
        Write-Host ($job.ChildJobs[0].JobStateInfo.Reason.Message)
        Write-Host ($job.ChildJobs[0].JobStateInfo.Reason)
        Receive-Job -Job $job
}
catch {
        Write-Host "Start-Job failed: "
        $_ | Format-List * -Force
}
finally {
        if($s) {
            Remove-PSSession -Session $s
        }
}


Viewing all articles
Browse latest Browse all 21975

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>