In this blog post we will take a look at how we can secure your end to end PowerShell Execution from vRO. Including how not to show passwords when using CredSSP in a double-hop authentication scenario.

We will take a look at few common use cases regarding the configuration of vRO, the PowerShell Host, the WinRM Protocol, and the PS Script/command and how we can best secure all of them.

WS-Management encrypts all traffic by default and this is controlled by the AllowUnencrypted client and server WinRM configuration parameter. Even if you only work with HTTP (which is the default configuration) and not with HTTPS. Prior to Windows Server 2003 R2 this WInRM in an HTTP session is not encrypted.

By default, PowerShell remoting authenticates using a “Network Logon”. Network Logons work by proving to the remote server that you have possession of the users credential without sending the credential to that server. Because the remote server doesn’t have possession of your credential, when you try to make the second hop (from Server A to Server B) it fails because Server A doesn’t have a credential to authenticate to Server B with.
To get around this issue, PowerShell provides the CredSSP option. When using CredSSP, PowerShell will perform a “Network Clear-text Logon” instead of a “Network Logon”. Network Clear-text Logon works by sending the user’s clear-text password to the remote server. When using CredSSP, Server A will be sent the user’s clear-text password, and will therefore be able to authenticate to Server B. Double hop works!

Microsoft has made changes to Windows Server 2012R2 and Windows 8.1 to eliminate clear-text credentials from being stored in memory. Additionally, even though your clear-text credential is not saved in memory, it is still sent to the remote server.

An additional layer of protection can be added by using WinRM with HTTPS . HTTPS doesn’t just add another encryption layer; its main purpose is to verify the authenticity of the remote machine, thereby preventing man-in-the-middle attacks.

So back the example.

As you have a double-hop authentication scenario you need to use CredSSP. Your starting script will most likely contain the following code:

As you can see the password is stored in plain text. After successfully securing it will no longer be exposed.

Use Case 1 (least secure)

This use case illustrates the worst use case scenario possible. In it every component is configured to allow unencrypted traffic and passwords are send in plain text over the network.
Consider the following configuration:

We have stored the password in plain text in our PowerShell script. The script is stored in vRO.

We have added an HTTP PowerShell Host. Therefore communication b/n vRO and the PowerShell host is not encrypted.

WinRM is set to allow unencrypted traffic (AllowUnencrypted=True). Therefore WinRM traffic when using CredSSP from out powershell host to our second server the password is send WinRM unencrypted in plain text.

The end destination server (on the CredSSP receiving side) is prior to Windows Server 2008 R2. Therefore the password is stored in plain text in memory and can easily be retrieved.

Illustrated this configuration will look something like this:

Lets explore another use case that shows more secure configuration.

Use Case 2

This use case illustrates a bit more secure scenario.
Consider the following configuration:

We have stored the password as SecureString in vRO . vRO cannot see the password in the WF. The password is still being send over the network to the PS Host in plain text.

We have added an HTTPS PowerShell Host. Therefore communication b/n vRO and the PowerShell host is encrypted. Although the password itself is send in plain text it is send over an encrypted HTTPS channel.

WinRM is set to deny unencrypted traffic (AllowUnencrypted=False). Therefore WinRM traffic when using CredSSP from our PowerShell host to our second server the password is send WinRM encrypted.

WinRM is configured to use HTTP and HTTPS, but we are not forcing HTTPS in our script code. Therefore traffic isunencrypted b/n server.

The end destination server (on the CredSSP receiving side) is newer then Windows Server 2008 R2. Therefore the password is no longer stored in plain text in memory.

Illustrated this configuration will look something like this:

Lets explore another use case that shows even more secure configuration.

Use Case 3 (Most Secure)

This use case illustrates a secure scenario.
Consider the following configuration:

We have converted out password as PowerShell SecureString Object and saved it in a file. That file can lie on the Windows Server or within vRO. vRO Users cannot see the password in plain text in the WF. Password in Plain Text from vRO to the PS Host server is not send, instead the PowerShell SecureString Object is send.

We have added an HTTPS PowerShell Host. Therefore communication b/n vRO and the PowerShell host is encrypted. HTTPS brings additional layer of protection on top of the use of PowerShell SecureString Object to encrypt the communication channel.

WinRM is set to deny unencrypted traffic (AllowUnencrypted=False). Therefore WinRM traffic when using CredSSP from our PowerShell host to our second server the password is send WinRM encrypted.

WinRM is configured to use HTTP and HTTPS. In addition we are using the–UseSSL switch in the Invoke-Command to force WinRM to use HTTPS. Therefore traffic isencrypted b/n servers. To go even further we may even delete the HTTP Listener so that only HTTPS communication is possible.

The end destination server (on the CredSSP receiving side) is newer then Windows Server 2008 R2. Therefore the password is no longer stored in plain text in memory.

Illustrated this configuration will look something like this:

Securing the PowerShell Password

In a typical scenario your script will contain similar code where CredSSP is used:

This an example of typical payload send by vRO when executing PowerShell commands. If we send the payload as it is the password is send over the network in plain text.
We can use the ConvertTo-SecureString and ConvertFrom-SecureString cmdlets to encrypt the password.

The ConvertTo-SecureString cmdlet converts encrypted standard strings into secure strings. It can also convert plain text to secure strings. The secure string created by the cmdlet can be used with cmdlets or functions that require a parameter of type SecureString. The secure string can be converted back to an encrypted, standard string using the ConvertFrom-SecureString cmdlet. This enables it to be stored in a file for later use.

If the standard string being converted was encrypted with ConvertFrom-SecureString using a specified key, that same key must be provided as the value of the Key or SecureKey parameter of the ConvertTo-SecureString cmdlet.

The ConvertFrom-SecureString cmdlet converts a secure string (System.Security.SecureString) to an encrypted standard string (System.String). Unlike a secure string, an encrypted standard string can be saved in a file for later use. The encrypted standard string can be converted back to a secure string by using the ConvertTo-SecureString cmdlet.

If an encryption key is specified by using the Key or SecureKey parameters, the Advanced Encryption Standard (AES) encryption algorithm is used. The specified key must have a length of 128, 192, or 256 bits, because those are the key lengths supported by the AES encryption algorithm. If no key is specified, the Windows Data Protection API (DPAPI) is used to encrypt the standard string representation.

Back to our example. We will use the simplest way and utilize the Windows Data Protection API (DPAPI) to the standard string (plain text password).

To do this we run once the following command on the PS Host to encrypt the plain text password:

Note that the account with which you are logged in to the Windows machine when running the command must be the same as the user account you are entering when adding the PS Host in vRO. Otherwise decrypting the password will not work and you should utilize other options like SecureKey to do the encryption.

The content of the MyEncryptedPassword.txt file looks similar to this:

If we run this script payload from vRO no password will be send over the network. Instead the password will be read from the file and decrypted straight on the PS Host.
Alternatively we can copy the entire content of the MyEncryptedPassword.txt file into our PowerShell script as follows:

Now when we run our PowerShell script from vRO it will send the encrypted password over the network. The password will still be decrypted on the PowerShell host itself.

Lets take a look into two network trace examples.

During the first we will have a plain text password in our script send from vRO.
During the second we will have a PS SecureString object storing the password
For both cases we are using an HTTP host so that we can examine the traffic.

In the first example when we examine the TCP Stream we can capture the encoded script send over the network