VMware Cloud Community
JCayetano
Enthusiast
Enthusiast
Jump to solution

Invoke-VMScript false positive results.

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 //

Invoke-VMScript -VM $VMName -ScriptText " $($tls10_cipher_temp=(Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002").Functions)" -GuestUser $GuestCred -GuestPassword $GuestPass -ScriptType PowerShell -ErrorAction Stop

// 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.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

$VMName = 'MyVM'

$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

View solution in original post

4 Replies
LucD
Leadership
Leadership
Jump to solution

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

JCayetano
Enthusiast
Enthusiast
Jump to solution

Awesome! thanks @LucD that made my day Smiley Wink

I had to also trim  the variable 'cause all the time the switch was going to the Default Smiley Sad

$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 Smiley Happy

pastedImage_40.png

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 '-' Smiley Happy

[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

pastedImage_42.png

$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  Smiley Wink

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

$VMName = 'MyVM'

$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

JCayetano
Enthusiast
Enthusiast
Jump to solution

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

          }

}

Reply
0 Kudos