Securing Your PowerShell Execution and Password in VMware vRealize Orchestrator

Spas_KaloferovIn this blog post we will look at how to secure your end-to-end PowerShell Execution from VMware vRealize® Orchestrator™ (vRO)—including how not to show passwords when using the Credential Security Support Provider (CredSSP) protocol in a double-hop authentication scenario.

Let’s look at a few common use cases regarding the configuration of vRO, the PowerShell host, the Windows Remote Management (WinRM) protocol, and the PowerShell script/command, and how we can best secure all of them.

Web Services (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 (the default configuration) and not with HTTPS. Prior to Windows Server 2003 R2, WinRM in an HTTP session was 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 user’s credential without sending the credential to that server. When you try to make the second hop (from Server A to Server B), it fails because Server A doesn’t have possession of your 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 to 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:

$username = "vmwareadministrator"
$password = "VMware1!"
$psHost = "lan1dc1"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Invoke-Command -ComputerName $psHost -ScriptBlock { SomeCommand } -Authentication CredSSP -credential $cred

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

Use Case 1 (Least Secure)

This use case illustrates the worst-case scenario. Every component is configured to allow unencrypted traffic, and passwords are sent 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 between vRO and the PowerShell host is not encrypted.
  • WinRM is set to allow unencrypted traffic (AllowUnencrypted=True). Therefore, when using CredSSP, WinRM sends the password unencrypted from our PowerShell host to our second server .
  • WinRM is configured to use HTTP. Therefore, traffic is unencrypted between servers.
  • The 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:

Securing Your PowerShell Execution and Password 1

Let’s explore another use case that shows a more secure configuration.

Use Case 2 (More Secure)

This use case illustrates a 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 sent over the network to the PS host in plain text.
  • We have added an HTTPS PowerShell host. Therefore, communication between vRO and the PowerShell host is encrypted. Although the password is sent in plain text, it is sent over an encrypted HTTPS channel.
  • WinRM is set to deny unencrypted traffic (AllowUnencrypted=False). Therefore, the password is sent WinRM encrypted when using CredSSP from our PowerShell host to our second server.
  • WinRM is configured to use HTTP and HTTPS, but we are not forcing HTTPS in our script code. Therefore, traffic is unencrypted between servers.
  • The destination server (on the CredSSP receiving side) is newer than Windows Server 2008 R2. Therefore, the password is no longer stored in plain text in memory.

This configuration will look like the graphic below.

VMware vRealize Orchestrator PowerShell Execution

Let’s explore another use case that shows an even more secure configuration.

Use Case 3 (Most Secure)

This use case illustrates a secure scenario.

Consider the following configuration:

  • We have converted our password to a 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 sent, instead the PowerShell SecureString Object is sent.
  • We have added an HTTPS PowerShell Host. Therefore, communication between vRO and the PowerShell host is encrypted. HTTPS brings an additional layer of protection to encrypt the communication channel on top of the use of the PowerShell SecureString Object.
  • WinRM is set to deny unencrypted traffic (AllowUnencrypted=False). Therefore, the password is sent WinRM encrypted when using CredSSP from our PowerShell host to our second server.
  • WinRM is configured to use HTTP and HTTPS. In addition, we are using the –UseSSL switch in Invoke-Command to force WinRM to use HTTPS. Therefore, traffic is encrypted between servers. To go even further, we may even delete the HTTP Listener so that only HTTPS communication is possible.
  • The destination server (on the CredSSP receiving side) is newer than 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 Your PowerShell Execution and Password 3

Securing the PowerShell Password

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

$username = "vmwareadministrator"
$password = "VMware1!"
$psHost = "lan1dc1"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Invoke-Command -ComputerName $psHost -ScriptBlock { SomeCommand } -Authentication CredSSP -credential $cred

This an example of typical payload sent by vRO when executing PowerShell commands. If we send the payload as it is, the password is sent 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:

<strong>"</strong> VMware1!<strong>"</strong> <strong>| ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:WindowsTempMyEncryptedPassword.txt"</strong>

Note that the account you use to log in to the Windows machine when running the command must be the same as the user account you enter 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:

<strong>PS C:_TMP&gt; Get-Content  .MyEncryptedPassword.txt
</strong><strong>01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e83f87deaad0ad489930981c12bb88210000000002000000000003660000c0000000100
</strong><strong>00000abce011db75e41c01d855ddbb1d858f20000000004800000a000000010000000258af14ec5af2229f2e30d75345487a218000000925c307b64
</strong><strong>59f34025a90c4c4a8c4816bd48a29f3c78695414000000e0501f5effc6a953a63f5c3fcc707baa5419f3c8</strong>

Now that we have a file containing an encrypted password, we can modify our PowerShell Script to utilize it. To do this we modify our PowerShell script as follows.

<strong>$username = "vmwareadministrator"
</strong><strong>$password = Get-Content "C:WindowsTEMPMyEncryptedPassword.txt" | ConvertTo-SecureString
</strong>$psHost = "lan1dc1"
<strong>$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password
</strong><strong>Invoke-Command -ComputerName </strong>$psHost <strong>-ScriptBlock { get-DNSServerSetting } -Authentication CredSSP -credential $cred</strong>

If we run this script payload from vRO, no password will be sent 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.

<strong>$password = Get-Content "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e83f87deaad0ad489930981c12bb88210000000002000000000003660000c000000010000000abce011db75e41c01d855ddbb1d858f20000000004800000a000000010000000258af14ec5af2229f2e30d75345487a218000000925c307b6459f34025a90c4c4a8c4816bd48a29f3c78695414000000e0501f5effc6a953a63f5c3fcc707baa5419f3c8 " | ConvertTo-SecureString</strong>

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.

Let’s look into two network trace examples.

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

In the first example, when we examine the TCP Stream, we can capture the encoded script sent over the network.

 vRO TPC Stream

We will now decode this base64 string twice.

PS C:_TMP&gt; $EncodedText = "WW5KdmEyVnlYM05sY21saGJHbDZaU0FuSkhWelpYSnVZVzFsSUQwZ0luWnRkMkZ5WlZ4aFpHMXBibWx6ZEhKaGRHOXlJ
Z29rY0dGemMzZHZjbVFnUFNBaVZrMTNZWEpsTVNFaUNpUndjMGh2YzNRZ1BTQWliR0Z1TVdSak1TSUtKR055WldRZ1BTQk9aWGN0VDJKcVpXTjBJRk41YzNS
bGJTNU5ZVzVoWjJWdFpXNTBMa0YxZEc5dFlYUnBiMjR1VUZORGNtVmtaVzUwYVdGc0lDMUJjbWQxYldWdWRFeHBjM1FnUUNna2RYTmxjbTVoYldVc0tFTnZi
blpsY25SVWJ5MVRaV04xY21WVGRISnBibWNnTFZOMGNtbHVaeUFrY0dGemMzZHZjbVFnTFVGelVHeGhhVzVVWlhoMElDMUdiM0pqWlNrcENrbHVkbTlyWlMx
RGIyMXRZVzVrSUMxRGIyMXdkWFJsY2s1aGJXVWdKSEJ6U0c5emRDQXRVMk55YVhCMFFteHZZMnNnZXlCblpYUXRSRTVUVTJWeWRtVnlVMlYwZEdsdVp5QjlJ
QzFCZFhSb1pXNTBhV05oZEdsdmJpQkRjbVZrVTFOUUlDMWpjbVZrWlc1MGFXRnNJQ1JqY21Wa0p5QU5DZzBLRFFvPQ0K"
PS C:_TMP&gt; $DecodedText = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedText))
PS C:_TMP&gt; $DecodedText
YnJva2VyX3NlcmlhbGl6ZSAnJHVzZXJuYW1lID0gInZtd2FyZVxhZG1pbmlzdHJhdG9yIgokcGFzc3dvcmQgPSAiVk13YXJlMSEiCiRwc0hvc3QgPSAibGF
uMWRjMSIKJGNyZWQgPSBOZXctT2JqZWN0IFN5c3RlbS5NYW5hZ2VtZW50LkF1dG9tYXRpb24uUFNDcmVkZW50aWFsIC1Bcmd1bWVudExpc3QgQCgkdXNlcm
5hbWUsKENvbnZlcnRUby1TZWN1cmVTdHJpbmcgLVN0cmluZyAkcGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZSkpCkludm9rZS1Db21tYW5kIC1Db21wd
XRlck5hbWUgJHBzSG9zdCAtU2NyaXB0QmxvY2sgeyBnZXQtRE5TU2VydmVyU2V0dGluZyB9IC1BdXRoZW50aWNhdGlvbiBDcmVkU1NQIC1jcmVkZW50aWFs
ICRjcmVkJyANCg0KDQo=
PS C:_TMP&gt; $EncodedText = "YnJva2VyX3NlcmlhbGl6ZSAnJHVzZXJuYW1lID0gInZtd2FyZVxhZG1pbmlzdHJhdG9yIgokcGFzc3dvcmQgPSAiVk13
YXJlMSEiCiRwc0hvc3QgPSAibGFuMWRjMSIKJGNyZWQgPSBOZXctT2JqZWN0IFN5c3RlbS5NYW5hZ2VtZW50LkF1dG9tYXRpb24uUFNDcmVkZW50aWFsIC1B
cmd1bWVudExpc3QgQCgkdXNlcm5hbWUsKENvbnZlcnRUby1TZWN1cmVTdHJpbmcgLVN0cmluZyAkcGFzc3dvcmQgLUFzUGxhaW5UZXh0IC1Gb3JjZSkpCklu
dm9rZS1Db21tYW5kIC1Db21wdXRlck5hbWUgJHBzSG9zdCAtU2NyaXB0QmxvY2sgeyBnZXQtRE5TU2VydmVyU2V0dGluZyB9IC1BdXRoZW50aWNhdGlvbiBD
cmVkU1NQIC1jcmVkZW50aWFsICRjcmVkJyANCg0KDQo="
PS C:_TMP&gt; $DecodedText = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedText))
PS C:_TMP&gt; $DecodedText
broker_serialize '$username = "vmwareadministrator"
$password = "VMware1!"
$psHost = "lan1dc1"
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @($username,(ConvertTo-SecureString -String
$password -AsPlainText -Force))
Invoke-Command -ComputerName $psHost -ScriptBlock { get-DNSServerSetting } -Authentication CredSSP -credential $cred'

Windows Powercell

You can see that we have captured the plain text password sent from vRO.

Now in the second example, let’s examine the traffic and see how the PS SecureString Object will be shown.

PS SecureString Object

As we can see, the password is not transferred over the network.

Adding SSL and therefore adding encryption on the HTTPS transport protocol level will enforce even more security. To do this, we need to add the host with HTTPS.

The post Securing Your PowerShell Execution and Password in VMware vRealize Orchestrator appeared first on VMware Professional Services and Education Insights.

Source: VMware Virtualization – blogs.vmware.com