Windows PowerShell cmdlets to secure PSCredential Objects

I have previously discussed securing credentials using Windows Powershell atPowershell: Securing credentials using the PSCredential class. In this article, I will discuss a number of cmdlets I have created to secure credentials using a Advanced Encryption Standard (AES) encryption key to retrieve the content from a encrypted standard string.

As I am using an encryption key and storing the information in a content file, I will be using ACLs on the NTFS filesytem to control access. Alternative methods could be to store the encryption key in a database or use a certificate to control access to the item. Also, in practice I will store the encryption key on a remote file server.

Firstly, we need to create the encryption key using the ‘New-EncryptionKey’ cmdlet to which we use the RNGCryptoServiceProvider class to generate a random byte array for the encryption length. By default, the cmdlet using a 32-byte array to support the AES 256-bit encryption length. The cmdlet also supports using 128-bit and 192-bit encryption lengths which a 16-byte and 24-byte array. The random byte array for the specified encryption length is generated and sends the output to a file which will be the encryption key content.

Once the content has sent to the output file, the content of random byte array is then removed from the current session.

# Creates an AES 256-bit encryption key at the location D:\Output\Keys\mykey.key
New-EncryptionKey -Output D:\Output\Keys\mykey.key 

# Creates an AES 192-bit encryption key at the location D:\Output\Keys\mykey.key
New-EncryptionKey -Bytes 24 -Output D:\Output\Keys\mykey.key

We have now created an encryption key so that we may now convert the secure string for a credential object password using the specified encryption key and sends the output to a password file using the ‘New-EncryptedString’ cmdlet. The cmdlet will retrieve the content of the specified file containing the encryption key and from the stored credential objects convert the secure string of the password to an encrypted standard string and send the output to a file and clear the content of the stored encryption key from the current session.

New-EncryptedString -KeyFile D:\Output\Keys\mykey.key -PasswordFile D:\Output\Passwords\mypassword.txt 

Finally we want to retrieve the credential object to use as a variable to pass to a subsequent cmdlet which will require authentication. The content of the password file is retrieved and converted to a secure string using the content of the encryption key and stored as a password variable and passed to the PSCredential class to represent a set of security credentials and return the object. For subsequent cmdlets I can use the ‘$Password.GetNetworkCredential().Password’ property value for authentication from the PSCredential object.

$Password = Get-PSCredentialObject -Username administrator -KeyFile D:\Output\Keys\mykey.key -PasswordFile D:\Output\Passwords\mypassword.txt 

The cmdlets are available from the below:

New-EncryptionKey – https://github.com/dean1609/PowerShell/blob/master/Functions/New-EncryptionKey.ps1
New-EncryptedString – https://github.com/dean1609/PowerShell/blob/master/Functions/New-EncryptedString.ps1
Get-PSCredentialObject – https://github.com/dean1609/PowerShell/blob/master/Functions/Get-PSCredentialObject.ps1

Part Two ‚Äď Computing email address hash value using Windows PowerShell

In part one I discussed computing the hash value using the MD5 hash algorithm for an email address, in this post I am going to discuss using other hash algorithms available in the HashAlgorithm Class to compute the value.

The available hash algorithms are MD5, RIPEMD160, SHA1, SHA256, SHA384 and SHA512 therefore in the advanced function we will set a parameter value which validates the input provided. By default, the hash algorithm of MD5 will be used unless specified.

The script block to compute the hash value does not differ from the example provided in the previous example which uses the StringBuilder Class .NET Framework object, other than we pass the hash algorithm parameter to the HashAlgorithm Class to compute the value.

Now be invoking the function and specifying a hash algorithm to compute the hash value I am able to use the default MD5 in the first instance and then each of the hash algorithms specified in the class.

Create-EmailHashPartTwoOutput

In the final part, I will look at using the  Blowfish-based hashing algorithm to compute the hash value and have an available advanced function and also provide the ability to specify not only an email address but a string value to compute the hash value.

Part One – Computing email address hash value using Windows PowerShell

I was recently discussing tracking email addresses and in particular protecting sensitive information and ensuring that the email address may not be re-used on deactivation. This got me thinking of how we could achieve this using Windows PowerShell.

As the advanced function required an email address I wanted to validate the  parameter specified for an email address so that is was valid. In the initial scenario I used a match based on regular expression as below. The regex pattern should match 99.9% of valid email addresses, but only allows for letters, digits and a couple of special characters. The official definition specified in RFC 5322 is far more complex

  (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*
  |  "(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]
      |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])*")
@ (?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
  |  \[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}
       (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:
          (?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]
          |  \\[\x01-\x09\x0b\x0c\x0e-\x7f])+)
     \])

However, I found that this generated what could be considered as an unfriendly error exception message, if the validation of the patten was returned as ‘false’.

 Cannot validate argument on parameter 'Email'. The "$_ -match "\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b"" validation script for the argument with value "someone@where" did not return a result of True

Therefore I decided to modify the script block for the parameter validation to throw an error if the validation of the pattern was returned as ‘false’,

This would now return the error exception message:

The email address someone@where is not a valid email address format.

So, lets now look at computing the hash value for the string provided as a valid email address. By default, Windows PowerShell only provides the Get-FileHash cmdlet to compute the hash value for a file by using a specified hash algorithm.

In the initial instance I used the MD5 hash algorithm by creating a StringBuilder Class .NET Framework object  and invoking the HashAlgorithm Class to compute the hash value.

This would return the following output when computing the hash algorithm:

CreateEmailHashMD5

Now we are all aware that MD5 contains weaknesses and we should not be using this as hashing algothrim for sensitive information so I will look at using alternative hashing algorithms and the Blowfish-based hashing algorithm (one good thing they were doing at Ashley Madison!) in additional posts covering this topic.

 

Security ‚Äď Part Five: Security Profile, Services and Firewall

When an ESXi host system is installed by default the firewall is enabled. All incoming and outgoing ports are blocked except the default TCP and UDP ports using for Management Services. The ESXi firewall protects the management interface of the ESXi host system, but provides no protection to virtual machines. By default, the following management services are open:

Management Service Description
lbtd (/sbin/net-lbtd) Load balancing teaming for distributed switches is an operation that evaluates the uplink load
vpxa (/usr/lib/vmware/vpxa/bin/vpxa) Virtual Center Agent to enable communication from the vCenter Server System to hostd service on the ESXi host system.
NTP Daemon (/sbin/ntpd) Network Time Protocol Daemon to synchronise the time between the ESXi host system and either a stratum or an atomic clock over the network
Direct Console UI (/sbin/dcui) Direct Console User Interface to enable the starting and stopping of the system and to perform limited setup, maintenance and troubleshooting tasks.
CIM Server (/bin/cimslp) Common Interface Model interface to monitor and manage health of the manager server hardware

In addition to the management services, by default the following ports are open for management access on the ESXi host system:

Port Description
22 SSH Server for incoming TCP
53 DNS client for incoming and outgoing UDP
68 DHCP client for incoming and outgoing UDP
161 SNMP server for incoming UDP
80 Fault tolerance for incoming TCP and outgoing TCP and UDP
427 CIM client SLPv2 to discover server for incoming and outgoing UDP
443 HTTPS access for incoming TCP
902 Host access and heartbeat for incoming and outgoing TCP and outgoing UDP
1234, 1235 vSphere replication for outgoing TCP
5988 CIM transactions over HTTP for incoming TCP
5989 CIM XML transactions over HTTPS for incoming and outgoing TCP
8000 vMotion requests for incoming and outgoing TCP
8100, 8200 Fault tolerance traffic for incoming and outgoing TCP and UDP

In order to protect the management interface the ESXi host system uses firewall rulesets to allow and disallow access to the ESXi host system. The default rulesets are defined initially in the read-only ‘/etc/vmware/firewall/service.xml’ file. To retrieve a list of firewall rule sets invoke the esxcli network firewall namespace.

esxli network firewall ruleset list

In addition to the firewall rulesets, more detailed information maybe retrieved:

esxli network firewall ruleset rule list

The ESX host system firewall ports and services can be made either using the vSphere Web Client, using the esxcli command line tool or using PowerCLI.

Configuring Firewall Service Properties Using vSphere Web Client

1) Select the ESXi host system to configure the Firewall service properties.

2) Browse to Manage > Settings > Security Profile > Services and select Edit.

Configure the ESXi Firewall Properties Using vSphere Web Client

1) Select the ESXi host system to configure the Firewall properties.

2) Browse to Manage > Settings > Security Profile > Firewall and Edit.

Configure the ESXi Firewall Using PowerCLI 

To retrieve information regarding the ESXi Firewall we can invoke both the Get-VMHostService and Get-VMHostFirewallException cmdlets.

1) For retrieving the status of services running on the ESXi host system, invoke the following:

Get-VMHost esxi1.dean.local | Get-VMHostService

2) To retrieve more detailed information for the incoming and outgoing service ports for each service invoke the following:

Get-VMHost esxi1.dean.local | Get-VMHostFirewallException | Where-Object {$_.Enabled}

By default, management services on the ESXi host system are enabled to provide local and remote client access and allowed through the firewall if the service ports are open. For Example, the syslog service is enabled on the ESXi host system but the firewall service ports are not allowing outbound connections. To modify the configuration using the esxcli network firewall namespace, perform the following steps.

1) Connect to the ESXi host system using an SSH client.

2) Retrieve the status of the syslog ruleset status.

esxcli network firewall ruleset list | grep syslog
syslog false

3) Enable the syslog firewall service.

esxcli network firewall ruleset set -e true -r syslog

We may also disable the syslog firewall service by invoking the following using the esxcli network firewall namespace.

esxcli network firewall ruleset set -e false -r syslog

There may be certain scenarios where the you may need to add more services than those preconfigured on the ESXi host system, in order to perform this action we must create a configuration file in the directory ‘/etc/vmware/firewall’. In this example, I will configure a service named ‘DeanTestApplication’ to enable inbound¬†connectivity on TCP service port 3210 where the default state will be disabled.

1) Connect to the ESXi host system using an SSH client.

2) Create the following file ‘/etc/vmware/firewall/deantestapplication.xml’, with the following configuration.

<! -- Firewall information for Dean Test Application -->
<ConfigRoot>
  <service>
    <id>DeanTestApplication</id>
    <rule id='0000'>
      <direction>inbound</direction>
      <protocol>tcp</protocol>
      <porttype>dst</porttype>
      <port>3210</port>
    </rule>
  </service>
</Config>

3) Save the file and reload the firewall, which will restart the services listed for the firewall.

esxcli network firewall refresh

Once the firewall has been reloaded we can use the vSphere Web Client to confirm if the firewall service has been loaded into memory and further configure the service. Alternatively, we can confirm this form the esxcli network firewall namespace:

esxcli network firewall ruleset list | grep DeanTestApplication
DeanTestApplication false

Security ‚Äď Part Four: Enabling ESXi Lockdown Mode

To increase the security of an ESXi host system which is being managed by a vCenter Server system you can enable Lockdown Mode to restrict users from performing actions directly on an ESXi host using SSH or the ESXi shell. Also, users without the DCUI Access privelage will be restricted from accessing the DCUI. As Lockdown Mode restricts access all actions on managed ESXi host systems must be performed using a connection to the vCenter Server system using an account with necessary permissions.

Lockdown Mode is only available when an ESXi host system is managed by a vCenter Server and can be enabled and disabled using the following methods.

Configuring Lockdown Mode using the vSphere Web Client 

1) Select the ESXi host system you wish to configure Lockdown Mode.

2) Browse to Manage  > Security Profile > Lockdown Mode and select Edit

3) Enable or Disable the Lockdown Mode checkbox and select OK.

Configuring Lockdown Mode using the ESXi Shell Command Line

1) Connect to the ESXi host system using an SSH client.

2) To retrieve the status of Lockdown mode, invoke the following:

~ # vim-cmd -U dcui vimsvc/auth/lockdown_is_enabled
false

3) To enable Lockdown Mode, invoke the following:

~ # vim-cmd -U dcui vimsvc/auth/lockdown_mode_enter

4) To disable Lockdown Mode, invoke the following:

~ # vim-cmd -U dcui vimsvc/auth/lockdown_mode_exit

Configure Lockdown Mode Using the Direct Console User Interface

1) Connect to the ESXi host system using the DCUI.

2) Press F2 to customise the system.

3) Select Configure Lockdown Mode

4) Enable or Disable Lockdown Mode using the spacebar to toggle the configuration state.

5) Select OK.

Configure Lockdown Mode using PowerCLI

1) Connect to the ESXi host system using the Connect-VIServer cmdlet.

2) To retrieve the status of the Lockdown Mode, invoke the following using the Get-VMHost cmdlet.

Get-VMHost esxi1.dean.local | Select Name, @{N="Lockdown Mode";E={$_.ExtensionData.Config.adminDisabled}}

3) Invoke the following to enable Lockdown Mode using the Get-View cmdlet.

(Get-VMHost esxi1.dean.local | Get-View).EnterLockdownMode() | Get-VMHost | Select Name, @{N="Lockdown Mode";E=$_ExtensionData.Config.AdminDisabled}} 

4) Invoke the following to disable Lockdown Mode using the Get-View cmdlet

(Get-VMHost esxi1.dean.local | Get-View).ExitLockdownMode()

 

 

Security ‚Äď Part Three: Generating ESXi Host Certificates

In order to secure connections between clients, ESXi host systems and the vCenter Server system SSL is used. When an ESXi host system or vCenter Server system is installed, the installation will include SSL certificates by default to establish an initial connection. In order to connect ESXi host systems to a managed vCenter Server system and to connect to those managed objects the SSL certificate is used.

For SSL certificates generated in VMware products these use standard X.509 version 3 (x.509v3) certificates to encrypt session information over the SSL protocol connections between the client and the server.  When replacing the default ESXi host system and vCenter Server system you are required to generate your SSL certificates to conform to the Privacy Enhanced Mail (PEM) key format and to be signed. The key used to sign certificates must be a standard RSA key with an encryption length which ranges between 512 and 4.096 bits, where the VMware recommendation is 2,048.

If you replace a certificate with one signed by your own local root CA or plan to use the default certificates, you must pre-trust the certificate by importing into the local certificate store for each vSphere Client instance. For certificates signed by a local root CA you must pre trust any valid default certificates you will continue to use on the vCenter Server system. For ESXi host systems that are exposed to the internet, you should use a trusted commercial security authority.

On an ESXi host system, the two default certificate files are located at:

  • Private Key – /etc/vmware/ssl/rui.key
  • Certification File – /etc/vmware/ssl/rui.crt

In order to replace the default SSL certificates perform the following on an ESXi host system:

1) Connect to the ESXi host system using a SSH client as root user.

2) Create a backup of the existing certificates if they exist on the ESXi host system.

/etc/vmware/ssl # mv rui.crt rui.crt.backup
/etc/vmware/ssl # mv rui.key rui.key.backup

3) Generate the new certificates on the ESXi host system or replace the default certificate with CA signed certificate.

/bin # generate-certificates

4) Restart the services or alternatively restart the ESXi host system.

services.sh restart

We may also configure timeout values that can affect the SSL connection for when a connection becomes idle that can be configured for an ESXi host system. By default, SSL connections between the server and the client do not timeout. There are two timeout settings which can be configured on an ESXi host system, these being:

  • Read Timeout – connections that have completed the SSL handshake process using TCP service port 443 of the ESXi host system.
  • Handshake Timeout – connections that have not completed the SSL handshake process using TCP service port 443 of the ESXi host system.

The timeout values can be configured by connecting to an ESXi host system using a SSH client and modifying the file ‘/etc/vmware/hostd/config.xml’ file and adding the below¬†which requires a¬† restart of the vmware-hostd process to apply the configuration change.

<vmacore>
  <http>
     <readTimeoutMs>20000</readTimeoutMs>
  </http>
  <ssl>
    <handshakeTimeoutMs>20000</handshakeTimeoutMs>
  </ssl>
</vmacore>
services.sh restart

Security ‚Äď Part Two: Configure ESXi Host SSH Settings

In order to access an ESXi host system using a SSH client there is a requirement to connect to the remote host. By default, the ESXi host system does not enable SSH connections and therefore there is a requirement to enable access to an ESXi host system to use SSH. This can be performed from the vSphere Web Client by performing the following:

1) Select the ESXi host system you require to enable SSH.

2) Select Manage > Security Profile > Services and select Edit.

3) Select the SSH service and select Start.

I have previously written about enabling the SSH service on multiple ESXi host systems using PowerCLI at https://deangrant.wordpress.com/2014/08/19/powercli-starting-and-stopping-the-ssh-service-on-multiple-esxi-hosts/.

By default the startup policy will be configured to be stop and start manually, on restart of the ESXi host system the service will not be started on startup. To secure the SSH connectivity further you may configure a timeout value for each connection. In order to configure a timeout value we will need to modify the advanced settings of the ESXi host system for the value ‘UserVars.ESXiShellTimeout’ which can be performed in the vSphere Web Client as follows:

1) Select the ESXi host system you require to configure a SSH timeout value

2) Select Manage > Advanced System Settings

3) Browse to the value ‘UserVars.ESXiShellTimeout’ and select Edit.

The value in seconds can be set from 0 (no timeout value) to 86,400 seconds.  Alternatively, you can use PowerCLI and the Set-AdvancedSetting cmdlet to configure this value as below to configure a timeout value of one hour.

Get-VMHost esxi1.dean.local | Get-AdvancedSetting -Name "UserVars.ESXiShellTimeOut" | Set-AdvancedSetting -Value "3600" -Confirm:$False