diff --git a/staging/provisioning/windows/windowssecuretls.ps1 b/staging/provisioning/windows/windowssecuretls.ps1 new file mode 100644 index 0000000000..55625bfafd --- /dev/null +++ b/staging/provisioning/windows/windowssecuretls.ps1 @@ -0,0 +1,385 @@ +#*************************************************************************************************************** +# It does the following: +# * Disable TLS 1.O, TLS 1.1, SSLv2, SSLv3 and enables TLS1.2 +# * The CipherSuite order is set to the SDL approved version. +# * The FIPS MinEncryptionLevel is set to 3. +# * RC4 is disabled +#*************************************************************************************************************** + +#******************* FUNCTION THAT ACTUALLY UPDATES KEYS *********************** +function Set-CryptoSetting { + param ( + $regKeyName, + $value, + $valuedata, + $valuetype + ) + + # Check for existence of registry key, and create if it does not exist + If (!(Test-Path -Path $regKeyName)) { + New-Item $regKeyName | Out-Null + } + + # Get data of registry value, or null if it does not exist + $val = (Get-ItemProperty -Path $regKeyName -Name $value -ErrorAction SilentlyContinue).$value + + + If ($val -eq $null) { + # Value does not exist - create and set to desired value + New-ItemProperty -Path $regKeyName -Name $value -Value $valuedata -PropertyType $valuetype | Out-Null + } + Else { + # Value does exist - if not equal to desired value, change it + If ($val -ne $valuedata) { + Set-ItemProperty -Path $regKeyName -Name $value -Value $valuedata + } + } +} +#*************************************************************************************************************** + +#******************* FUNCTION THAT DISABLES RC4 *********************** +function DisableRC4 { + $subkeys = Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL" + $ciphers = $subkeys.OpenSubKey("Ciphers", $true) + + Write-Log "----- Checking the status of RC4 -----" + + $RC4 = $false + if ($ciphers.SubKeyCount -eq 0) { + $k1 = $ciphers.CreateSubKey("RC4 128/128") + $k1.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) + $k2 = $ciphers.CreateSubKey("RC4 64/128") + $k2.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) + $k3 = $ciphers.CreateSubKey("RC4 56/128") + $k3.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) + $k4 = $ciphers.CreateSubKey("RC4 40/128") + $k4.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) + + Write-Log "RC4 was disabled " + $RC4 = $true + } + + If ($RC4 -ne $true) { + Write-Log "There was no change for RC4 " + } +} +#*************************************************************************************************************** + +#******************* FUNCTION CHECKS FOR PROBLEMATIC FIPS SETTING AND FIXES IT *********************** +function Test-RegistryValueForFipsSettings { + $fipsPath = @( + "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", + "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services", + "HKLM:\System\CurrentControlSet\Control\Terminal Server\DefaultUserConfiguration" + ) + + $fipsValue = "MinEncryptionLevel" + + foreach ($path in $fipsPath) { + Write-Log "Checking to see if $($path)\$fipsValue exists" + + $ErrorActionPreference = "stop" + Try { + $result = Get-ItemProperty -Path $path | Select-Object -ExpandProperty $fipsValue + if ($result -eq 4) { + set-itemproperty -Path $path -Name $fipsValue -value 3 + Write-Log "Regkey $($path)\$fipsValue was changed from value $result to a value of 3" + } + else { + Write-Log "Regkey $($path)\$fipsValue left at value $result" + } + + } + Catch [System.Management.Automation.ItemNotFoundException] { + Write-Log "Reg path $path was not found" + } + Catch [System.Management.Automation.PSArgumentException] { + Write-Log "Regkey $($path)\$fipsValue was not found" + } + Catch { + Write-Log "Error of type $($Error[0].Exception.GetType().FullName) trying to get $($path)\$fipsValue" + } + Finally { + $ErrorActionPreference = "Continue" + } + } +} +#*************************************************************************************************************** + +#********************************TLS CipherSuite Settings ******************************************* + +# CipherSuites for windows OS < 10 +function Get-BaseCipherSuitesOlderWindows() +{ + param + ( + [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder + ) + $cipherorder = @() + + if ($isExcellenceOrder -eq $true) + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256" + } + else + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384" + } + + # Add additional ciphers when EnableOlderTlsVersions flag is set to true + if ($EnableOlderTlsVersions) + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" + $cipherorder += "TLS_RSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_RSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA" + $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA" + } + return $cipherorder +} + +# Ciphersuites needed for backwards compatibility with Firefox, Chrome +# Server 2012 R2 doesn't support TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +# Both firefox and chrome negotiate ECDHE_RSA_AES_256_CBC_SHA1, Edge negotiates ECDHE_RSA_AES_256_CBC_SHA384 +function Get-BrowserCompatCipherSuitesOlderWindows() +{ + param + ( + [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder + ) + $cipherorder = @() + + if ($isExcellenceOrder -eq $true) + { + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384" # (uses SHA-1) + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" # (uses SHA-1) + } + else + { + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" # (uses SHA-1) + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384" # (uses SHA-1) + } + return $cipherorder +} + +# Ciphersuites for OS versions windows 10 and above +function Get-BaseCipherSuitesWin10Above() +{ + param + ( + [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder + ) + + $cipherorder = @() + if ($isExcellenceOrder -eq $true) + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + } + else + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" + } + # Add additional ciphers when EnableOlderTlsVersions flag is set to true + if ($EnableOlderTlsVersions) + { + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256" + $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" + $cipherorder += "TLS_RSA_WITH_AES_256_GCM_SHA384" + $cipherorder += "TLS_RSA_WITH_AES_128_GCM_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA256" + $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA" + $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA" + } + + return $cipherorder +} + +#******************************* TLS Version Settings **************************************************** + +function Get-RegKeyPathForTls12() +{ + $regKeyPath = @( + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" + ) + return $regKeyPath +} + +function Get-RegKeyPathForTls11() +{ + $regKeyPath = @( + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" + ) + return $regKeyPath +} + +function Get-RegKeypathForTls10() +{ + $regKeyPath = @( + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" + ) + return $regKeyPath +} + +function Get-RegKeyPathForSsl30() +{ + $regKeyPath = @( + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server" + ) + return $regKeyPath +} + +function Get-RegKeyPathForSsl20() +{ + $regKeyPath = @( + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client", + "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server" + ) + return $regKeyPath +} + +#******************************* Wrap TLSSettings.ps1 to a function without restart ********************** + +function Enable-SecureTls { + $registryPathGoodGuys = @() + $registryPathBadGuys = @() + + Write-Log -Message "========== Start of logging for Enable-SecureTls ==========" + # we enable TLS 1.2 and disable others + $registryPathGoodGuys += Get-RegKeyPathForTls12 + + $registryPathBadGuys += Get-RegKeyPathForSsl20 + $registryPathBadGuys += Get-RegKeyPathForSsl30 + $registryPathBadGuys += Get-RegKeypathForTls10 + $registryPathBadGuys += Get-RegKeyPathForTls11 + Write-Log "Enabling TLS1.2. Disabling TLS1.1, TLS1.0, SSL3.0, SSL2.0" + + Write-Log "Check which registry keys exist already and which registry keys need to be created." + + #******************* CREATE THE REGISTRY KEYS IF THEY DON'T EXIST******************************** + # Check for existence of GoodGuy registry keys, and create if they do not exist + For ($i = 0; $i -lt $registryPathGoodGuys.Length; $i = $i + 1) { + Write-Log "Checking for existing of key: $($registryPathGoodGuys[$i]) " + If (!(Test-Path -Path $registryPathGoodGuys[$i])) { + New-Item $registryPathGoodGuys[$i] | Out-Null + Write-Log "Creating key: $($registryPathGoodGuys[$i]) " + } + } + + # Check for existence of BadGuy registry keys, and create if they do not exist + For ($i = 0; $i -lt $registryPathBadGuys.Length; $i = $i + 1) { + Write-Log "Checking for existing of key: $($registryPathBadGuys[$i]) " + If (!(Test-Path -Path $registryPathBadGuys[$i])) { + Write-Log "Creating key: $($registryPathBadGuys[$i]) " + New-Item $registryPathBadGuys[$i] | Out-Null + } + } + + #******************* EXPLICITLY DISABLE SSLV2, SSLV3, TLS10 AND TLS11 ******************************** + For ($i = 0; $i -lt $registryPathBadGuys.Length; $i = $i + 1) { + if ($registryPathBadGuys[$i].Contains("Client") -Or $registryPathBadGuys[$i].Contains("Server")) { + Write-Log "Disabling this key: $($registryPathBadGuys[$i]) " + Set-CryptoSetting $registryPathBadGuys[$i].ToString() Enabled 0 DWord + Set-CryptoSetting $registryPathBadGuys[$i].ToString() DisabledByDefault 1 DWord + } + } + + #********************************* EXPLICITLY Enable TLS12 **************************************** + For ($i = 0; $i -lt $registryPathGoodGuys.Length; $i = $i + 1) { + if ($registryPathGoodGuys[$i].Contains("Client") -Or $registryPathGoodGuys[$i].Contains("Server")) { + Write-Log "Enabling this key: $($registryPathGoodGuys[$i]) " + Set-CryptoSetting $registryPathGoodGuys[$i].ToString() Enabled 1 DWord + Set-CryptoSetting $registryPathGoodGuys[$i].ToString() DisabledByDefault 0 DWord + } + } + + #************************************** Disable RC4 ************************************************ + DisableRC4 + + #************************************** Set Cipher Suite Order ************************************** + Write-Log "----- starting ciphersuite order calculation for excellence cipher suite order -----" + $cipherlist = @() + + if ([Environment]::OSVersion.Version.Major -lt 10) + { + $cipherlist += Get-BaseCipherSuitesOlderWindows -isExcellenceOrder $true + $cipherlist += Get-BrowserCompatCipherSuitesOlderWindows -isExcellenceOrder $true + } + else + { + $cipherlist += Get-BaseCipherSuitesWin10Above -isExcellenceOrder $true + } + $cipherorder = [System.String]::Join(",", $cipherlist) + Write-Log "Appropriate ciphersuite order : $cipherorder" + + $CipherSuiteRegKey = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002" + + if (!(Test-Path -Path $CipherSuiteRegKey)) + { + New-Item $CipherSuiteRegKey | Out-Null + Write-Log "Creating key: $($CipherSuiteRegKey) " + } + + $val = (Get-Item -Path $CipherSuiteRegKey -ErrorAction SilentlyContinue).GetValue("Functions", $null) + Write-Log "Previous cipher suite value: $val " + Write-Log "New cipher suite value : $cipherorder " + + if ($val -ne $cipherorder) + { + Write-Log "Cipher suite order needs to be updated. " + Set-ItemProperty -Path $CipherSuiteRegKey -Name Functions -Value $cipherorder + Write-Log "Cipher suite value was updated. " + } + else + { + Write-Log "Cipher suite order does not need to be updated. " + Write-Log "Cipher suite value was not updated as there was no change. " + } + + #****************************** CHECK THE FIPS SETTING WHICH IMPACTS RDP'S ALLOWED CIPHERS ************************** + #Check for FipsSettings + Write-Log "Checking to see if reg keys exist and if MinEncryptionLevel is set to 4" + Test-RegistryValueForFipsSettings + + Write-Log -Message "========== End of logging for Enable-SecureTls ==========" +} \ No newline at end of file