4 Replies Latest reply on Feb 12, 2020 8:28 AM by JCayetano

    Invoke-VMScript false positive results.

    JCayetano Novice

      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. Re: Invoke-VMScript false positive results.
          LucD Guru
          User ModeratorsvExpertCommunity Warriors

          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: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
          • 2. Re: Invoke-VMScript false positive results.
            JCayetano Novice

            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 

            • 3. Re: Invoke-VMScript false positive results.
              LucD Guru
              Community WarriorsUser ModeratorsvExpert

              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: http://lucd.info | Twitter: @LucD22 | PowerCLI Reference co-author: http://tinyurl.com/hkn4glz
              • 4. Re: Invoke-VMScript false positive results.
                JCayetano Novice

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