Hello folks,
I have a silly question and a second set of ideas:
This thing it is been driving me so crazy since last night.
*** So the goal it is to query a Multi-string windows registry key , if the value it is found then remove it.
Path: "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002"
OS: Windows 2008 r2
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
How can I accomplish this? , super easy .
Query the Windows registry
if the value it is found
then
create a temporary array without the values in question which it is going to be replaced later.
if not then all good.
// To get the Values from the registry //
// This will compare if the
$somevariable=@($tls10_cipher_temp -like 'TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256').Count -gt 0
switch ($somevariable) {
$true { Write-Host "Cipher Suite found: `t The script will remove it"; $tls10_cipher=$tls10_cipher_temp | Where-Object { $_ -notlike "TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256*"}
Invoke-VMScript -VM $VMName -ScriptText "New-ItemProperty -path ""$tls_cipher_path"" -PropertyType 'MultiString' -Name Functions -Value $tls10_cipher -Force " -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell
}
$false { Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$true]"-f Green; write-host "`n`tCurrentValue:$tls_cipher_temp"}
Default { Write-Host "Unable to validate the TLS 1.0 cipher suite , please check your values"}
}
it looks so simple to get this done...
however I am stuck , because the Invoke-VMScript it is giving me a false positive , when I query the registry , it says the value was found .
and when gets time to evaluate $somevariable it contains "false" , which it is not true because I already removed manually those 2 strings.
What surprised me . If I perform the same command on the server it says the value was not found ,
PS C:\Users\jc~> $tls10_cipher_temp | Where-Object {$_ -like 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256'}
PS C:\Users\jc~> $tls10_cipher_temp | Where-Object {$_ -like 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256'}
PS C:\Users\jc~> $tls10_cipher_temp | Where-Object {$_ -like 'TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256'}
PS C:\Users\jc~> echo $tls10_cipher_temp
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_NULL_SHA256
TLS_RSA_WITH_NULL_SHA
SSL_CK_RC4_128_WITH_MD5
SSL_CK_DES_192_EDE3_CBC_WITH_MD5
PS C:\Users\jc~>
PS C:\Users\jc~> $test2=(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration
\Local\SSL\00010002").Functions
PS C:\Users\jc~> echo $test2
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_NULL_SHA256
TLS_RSA_WITH_NULL_SHA
SSL_CK_RC4_128_WITH_MD5
SSL_CK_DES_192_EDE3_CBC_WITH_MD5
PS C:\Users\jc~>
Then I was like how about if I combine all together without variables , maybe my problem it is on the variable types.
local server not found
PS C:\Users\jc~> @(((Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Loc
al\SSL\00010002").Functions)-like 'TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256').Count -gt 0
False
PS C:\Users\jca~> hostname
VM-SAFAL-38
PS C:\Users\jc~>
VMsrcipt it looks like it found it:
Invoke-VMScript -VM $VMName -ScriptText "$(@(((Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002").Functions)-like 'TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256').Count -gt 0 )" -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell -ErrorAction Stop
VM : vm-safal-38
ExitCode : 0
ScriptOutput : The term 'True' is not recognized as the name of a cmdlet, function, script fil
e, or operable program. Check the spelling of the name, or if a path was includ
ed, verify that the path is correct and try again.
At line:1 char:8
+ & {True <<<< }
+ CategoryInfo : ObjectNotFound: (True:String) [], CommandNotFoun
dException
+ FullyQualifiedErrorId : CommandNotFoundException
Uid : /VIServer=jc@~:443/VirtualMachine=VirtualMachine-vm-~/VMScriptResult=1076874359_0/
Length : 405
Test2: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256 TLS_ECDHE_RSA_WITH_AES_1
28_CBC_SHA256_P384 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256 TLS_ECDHE_RSA_WITH_AE
S_128_CBC_SHA_P384 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_R
SA_WITH_AES_256_CBC_SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P38
4 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384 TLS_ECDHE_ECDSA_WITH_AE
S_128_CBC_SHA256_P256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384 TLS_ECDHE
_ECDSA_WITH_AES_128_CBC_SHA_P256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 TLS_DHE_DSS_W
ITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_RC4_1
28_MD5 TLS_RSA_WITH_NULL_SHA256 TLS_RSA_WITH_NULL_SHA SSL_CK_RC4_128_WITH_MD5 SSL_CK_DES_192_EDE3_CBC_WITH_MD5
$tls10_cipherchecks= @($tls10_cipher_temp -like 'TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256').Count -gt 0
TLS10_cipherchecks: True
so why the Invoke-VMScript found it ?
I also reboot the server .
Any thoughts ?
Regards.
Instead of doing the testing on the target VM, why not do the testing on the station where you run the script?
That way you also have the old values of the registry entry.
Note1: I used here strings for the script to be executed on the target
Note2: I used the call to ExpandString to replace variables in the code
Note3: with a back-tick I escape the dollar sign in variables I do not want to be substituted
Note4: the ScriptOutput property is all output in 1 string. I remove the <LF> and split the string on the <CR>. That results in an array with the values.
Note5: I used splatting to place all parameter values in a hash table. That makes it easier to read and allows me to do the ExpandString call
$user = 'domain\user'
$pswd = 'VMware1!'
$path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002'
$cred = [PSCredential]::new($user, (ConvertTo-SecureString -String $pswd -AsPlainText -Force))
$code = @"
Get-ItemProperty -Path $path | Select -ExpandProperty Functions
"@
$codeUpdate = @'
`$sItem = @{
Path = '$path'
PropertyType = 'MultiString'
Name = 'Functions'
Value = $tlsciphersNewArray
Force = `$true
}
New-ItemProperty @sItem
'@
$sInvoke = @{
VM = $VMName
ScriptText = $code
GuestCredential = $cred
ScriptType = 'PowerShell'
ErrorAction = 'Stop'
}
$result = Invoke-VMScript @sInvoke
$tlsciphers = $result.ScriptOutput.Replace("`r",'').Split("`n") | where{$_}
if($tlsciphers.Count -eq 0){
Write-Host "Unable to validate the TLS 1.0 cipher suite , please check your values"
}
else{
$tlsciphersNew = $tlsciphers | where{ $_ -notlike "TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256"}
$tlsciphersNewArray = ($tlsciphersNew | %{"'$_'"}) -join ','
if($tlsciphers.Count -gt $tlsciphersNew.Count){
Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$false]"-f Red
pause
$sInvoke = @{
VM = $VMName
ScriptText = $ExecutionContext.InvokeCommand.ExpandString($codeUpdate)
GuestCredential = $cred
ScriptType = 'PowerShell'
ErrorAction = 'Stop'
}
$result2 = Invoke-VMScript @sInvoke
break
}
else{
Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$true]"-f Green
break
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Your basic problem seems to be that you placed the value for the ScriptText parameter between double quotes.
That means that PowerShell will look for variable substitution.
In that process it will for example also replace $true with the string 'True', which is probably not what you want.
As a solution, and provided you don't want any variable substitution to take place, place the value for ScriptText between single quotes.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Awesome! thanks @LucD that made my day
I had to also trim the variable 'cause all the time the switch was going to the Default
$tlscipher_checks=Invoke-VMScript -VM $VMName -ScriptText '$(@(((Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002").Functions)-like "TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256").Count -gt 0 )' -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell -ErrorAction Stop
$tlscipher_checks=$tlscipher_checks.Trim()
write-host "tls_cipher: `n$tlscipher_checks";
switch ($tlscipher_checks) {
'True' { Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$false]"-f Red; pause; update_registry -VMName $VMName -VMName_tls tls10cipher; break }
'False' { Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$true]"-f Green; write-host "`n`tCurrent Value:`n$($tls10_cipher_temp[0] | Out-String )";break}
Default { Write-Host "Unable to validate the TLS 1.0 cipher suite , please check your values";break}
}
Result as expected
I am almost done ,2 things left
1.- I need to get the existing values from the Windows registry into an array
I remembered reading a post about the ScriptOutput but I can't figure it out .
I was about to start making some tricks against the variable to just display the result. something like $_ -replace '-'
[array]$tls10_cipher_temp=Invoke-VMScript -VM $VMName -ScriptText ' ((Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002").Functions)' -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell -ErrorAction Stop
$tls10_cipher_temp.GetType()
Module : CommonLanguageRuntimeLibrary
Assembly : mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
TypeHandle : System.RuntimeTypeHandle
DeclaringMethod :
BaseType : System.Array
UnderlyingSystemType : System.Object[]
FullName : System.Object[]
2.- Once I get all the values into an array I should be able to use the proceed with the follow:
$tls10_cipher=$tls10_cipher_temp | Where-Object { $_ -notlike "TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256"}
Invoke-VMScript -VM $VMName -ScriptText "New-ItemProperty -path ""$tls_cipher_path"" -PropertyType 'MultiString' -Name Functions -Value $tls_cipher -Force " -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell
Write-Host "TLS 1.0 Ciphers removed `nValidating the change"; validate_registry -VMName $VMName -VMName_tls tls10
If I am not mistaken the Multi-string values will only accept arrays if I am wrong then I can probably explore another way to remove the strings if found.
Any recommendation would help me
Instead of doing the testing on the target VM, why not do the testing on the station where you run the script?
That way you also have the old values of the registry entry.
Note1: I used here strings for the script to be executed on the target
Note2: I used the call to ExpandString to replace variables in the code
Note3: with a back-tick I escape the dollar sign in variables I do not want to be substituted
Note4: the ScriptOutput property is all output in 1 string. I remove the <LF> and split the string on the <CR>. That results in an array with the values.
Note5: I used splatting to place all parameter values in a hash table. That makes it easier to read and allows me to do the ExpandString call
$user = 'domain\user'
$pswd = 'VMware1!'
$path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002'
$cred = [PSCredential]::new($user, (ConvertTo-SecureString -String $pswd -AsPlainText -Force))
$code = @"
Get-ItemProperty -Path $path | Select -ExpandProperty Functions
"@
$codeUpdate = @'
`$sItem = @{
Path = '$path'
PropertyType = 'MultiString'
Name = 'Functions'
Value = $tlsciphersNewArray
Force = `$true
}
New-ItemProperty @sItem
'@
$sInvoke = @{
VM = $VMName
ScriptText = $code
GuestCredential = $cred
ScriptType = 'PowerShell'
ErrorAction = 'Stop'
}
$result = Invoke-VMScript @sInvoke
$tlsciphers = $result.ScriptOutput.Replace("`r",'').Split("`n") | where{$_}
if($tlsciphers.Count -eq 0){
Write-Host "Unable to validate the TLS 1.0 cipher suite , please check your values"
}
else{
$tlsciphersNew = $tlsciphers | where{ $_ -notlike "TLS_ECDHE_RSA_WITH_AES_*_CBC_SHA_P256"}
$tlsciphersNewArray = ($tlsciphersNew | %{"'$_'"}) -join ','
if($tlsciphers.Count -gt $tlsciphersNew.Count){
Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$false]"-f Red
pause
$sInvoke = @{
VM = $VMName
ScriptText = $ExecutionContext.InvokeCommand.ExpandString($codeUpdate)
GuestCredential = $cred
ScriptType = 'PowerShell'
ErrorAction = 'Stop'
}
$result2 = Invoke-VMScript @sInvoke
break
}
else{
Write-Host "`n`n`t`t`rTLS 1.0 ciphers Validation status: ..........[$true]"-f Green
break
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks LucD that made the day.!
I added the code inside a function so that will facilitate a lot of things
$vms= Import-CSV "$PSScriptRoot\tls_adhoc.csv"
function validate_registry {
param(
[string]$VMName,
[string]$VMName_tls
)
switch -wildcard ($VMName_tls) {
"tls10" { Write-Host "[-] Validation Windows TLS 1.0 registry key on: $VMName [-]`n please wait..." -ForegroundColor Cyan
<# Here the code that will check the TLS Ciphers 🙂 #>
.
..
....
}
}
foreach ($vm in $vms){
<# The follow lines will query the Windows registry and will also create the new TLS keys #>
try {
$vmn = $vm.vmname
validate_registry -VMName $vmn -VMName_tls tls10
} catch { Write-Host "`n`n`t`t`t [-] Unable to Validate the Protocol [-] `n`t`t`t`t The [ $vmn ] will be added to the Tls_Failure report" $Error -F Red
$vmn| Select-Object @{Name='Name';Expression={$_}} | Export-Csv -NoTypeInformation $tls_failurereport -Append
}
}