none
Remediation for Microsoft Windows Unquoted Uninstall Path Enumeration Vulnerability RRS feed

  • Question

  • Afternoon All,

    Currently pulling my hair out with this one, following from the Unquoted Service Path Enumeration Vulnerability fix we are needing to do the same for Uninstall path’s

    I have found the following script but am struggling to get it work,

    $BaseKeys = "HKLM:SystemCurrentControlSetServices", #Services
    "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall", #32bit Uninstalls
    "HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall" #64bit Uninstalls
    #Blacklist for keys to ignore
    $BlackList = $Null
    #Create an ArrayList to store results in
    $Values = New-Object System.Collections.ArrayList
    #Discovers all registry keys under the base keys
    $DiscKeys = Get-ChildItem -Recurse -Directory $BaseKeys -Exclude $BlackList -ErrorAction SilentlyContinue |Select-Object -ExpandProperty Name | %{($_.ToString().Split('') | Select-Object -Skip 1) -join ''}
    #Open the local registry
    $Registry = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')
    ForEach ($RegKey in $DiscKeys)
    {
    #Open each key with write permissions
    Try { $ParentKey = $Registry.OpenSubKey($RegKey, $True) }
    Catch { Write-Debug "Unable to open $RegKey" }
    #Test if registry key has values
    If ($ParentKey.ValueCount -gt 0)
    {
    $MatchedValues = $ParentKey.GetValueNames() | ?{ $_ -eq "ImagePath" -or $_ -eq "UninstallString" }
    ForEach ($Match in $MatchedValues)
    {
    #RegEx that matches values containing .exe with a space in the exe path and no double quote encapsulation
    $ValueRegEx = '(^(?!u0022).*s.*.[Ee][Xx][Ee](?< !u0022))(.*$)' $Value = $ParentKey.GetValue($Match)
    #Test if value matches RegEx
    If ($Value -match $ValueRegEx) { $RegType = $ParentKey.GetValueKind($Match)
    #Uses the matches from the RegEx to build a new entry encapsulating the exe path with double quotes
    $Correction = "$([char]34)$($Matches[1])$([char]34)$($Matches[2])"
    #Attempt to correct the entry
    Try { $ParentKey.SetValue("$Match", "$Correction", [Microsoft.Win32.RegistryValueKind]::$RegType) } Catch { Write-Debug "Unable to write to $ParentKey" }
    #Add a hashtable containing details of corrected key to ArrayList
    $Values.Add((New-Object PSObject -Property @{ "Name" = $Match "Type" = $RegType "Value" = $Value "Correction" = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" })) | Out-Null } } } $ParentKey.Close() }
    
    $Registry.Close() $Values | Select-Object ParentKey,Value,Correction,Name,Type

    when I run it as a whole I get these errors

    At line:24 char:64
    + ... gEx = '(^(?!u0022).*s.*.[Ee][Xx][Ee](?< !u0022))(.*$)' $Value = $Pare ...
    +                                                            ~~~~~~
    Unexpected token '$Value' in expression or statement.
    At line:32 char:63
    + ... .Add((New-Object PSObject -Property @{ "Name" = $Match "Type" = $RegT ...
    +                                                            ~~~~~~
    Unexpected token '"Type"' in expression or statement.
    At line:32 char:62
    + $Values.Add((New-Object PSObject -Property @{ "Name" = $Match "Type"  ...
    +                                                              ~
    The hash literal was incomplete.
    At line:32 char:166
    + ... tion" = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" })) | O ...
    +                                                                  ~
    Missing closing ')' in expression.
    At line:32 char:166
    + ... tion" = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" })) | O ...
    +                                                                  ~
    Missing ')' in method call.
    At line:22 char:1
    + {
    + ~
    Missing closing '}' in statement block or type definition.
    At line:19 char:1
    + {
    + ~
    Missing closing '}' in statement block or type definition.
    At line:13 char:1
    + {
    + ~
    Missing closing '}' in statement block or type definition.
    At line:32 char:168
    + ... n" = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" })) | Out- ...
    +                                                                 ~
    Unexpected token ')' in expression or statement.
    At line:32 char:169
    + ... " = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" })) | Out-N ...
    +                                                                 ~
    Unexpected token ')' in expression or statement.
    Not all parse errors were reported.  Correct the reported errors and try again.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : UnexpectedToken
    

    However when trying to break it down running the different lines powershell is just crashing out when running line 9

    Any idea’s?


    Thursday, June 28, 2018 1:43 PM

Answers

  • please try to use new script version: https://gallery.technet.microsoft.com/Windows-Unquoted-Service-190f0341

    original script contain whatif key and should not change anything - only display, but if you remove whatif at last string it shoul work

    please, test this script before executing in production, it was tested only on 2 laptops (I have not more, right now)


    The opinion expressed by me is not an official position of Microsoft

    • Marked as answer by Chrism88 Thursday, September 27, 2018 10:43 AM
    Sunday, July 15, 2018 10:13 PM

All replies

  • If you're not experienced in PowerShell, I would recommend searching for existing scripts that can perform this fix for you rather than trying to write it yourself.

    I would also recommend learning how to use the debugger (e.g., PowerShell ISE).


    -- Bill Stewart [Bill_Stewart]

    Thursday, June 28, 2018 3:08 PM
    Moderator
  • Ok made some progress but still having issues with is crashing out when I comment out line 34

    $BaseKeys = "HKLM:SystemCurrentControlSetServices", #Services
    "HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall", #32bit Uninstalls
    "HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall" #64bit Uninstalls
    #Blacklist for keys to ignore
    $BlackList = $Null
    #Create an ArrayList to store results in
    $Values = New-Object System.Collections.ArrayList
    #Discovers all registry keys under the base keys
    $DiscKeys = Get-ChildItem -Recurse -Directory $BaseKeys -Exclude $BlackList -ErrorAction SilentlyContinue |Select-Object -ExpandProperty Name | %{($_.ToString().Split('') | Select-Object -Skip 1) -join ''}
    #Open the local registry
    $Registry = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')
    ForEach ($RegKey in $DiscKeys)
    {
    #Open each key with write permissions
    Try { $ParentKey = $Registry.OpenSubKey($RegKey, $True) }
    Catch { Write-Debug "Unable to open $RegKey" }
    #Test if registry key has values
    If ($ParentKey.ValueCount -gt 0)
    {
    $MatchedValues = $ParentKey.GetValueNames() | ?{ $_ -eq "ImagePath" -or $_ -eq "UninstallString" }
    ForEach ($Match in $MatchedValues)
    {
    #RegEx that matches values containing .exe with a space in the exe path and no double quote encapsulation
    $ValueRegEx = '(^(?!u0022).*s.*.[Ee][Xx][Ee](?< !u0022))(.*$)'
    $Value = $ParentKey.GetValue($Match)
    #Test if value matches RegEx
    If ($Value -match $ValueRegEx) { $RegType = $ParentKey.GetValueKind($Match)
    #Uses the matches from the RegEx to build a new entry encapsulating the exe path with double quotes
    $Correction = "$([char]34)$($Matches[1])$([char]34)$($Matches[2])"
    #Attempt to correct the entry
    Try { $ParentKey.SetValue("$Match", "$Correction", [Microsoft.Win32.RegistryValueKind]::$RegType) } Catch { Write-Debug "Unable to write to $ParentKey" }
    #Add a hashtable containing details of corrected key to ArrayList
    $Values.Add((New-Object PSObject -Property @{ "Name" = $Match "Type" = $RegType "Value" = $Value "Correction" = $Correction "ParentKey" = "HKEY_LOCAL_MACHINE$RegKey" )) | Out-Null } } } $ParentKey.Close() }
    
    
    $Registry.Close() 
    $Values | Select-Object ParentKey,Value,Correction,Name,Type

    Thursday, June 28, 2018 3:09 PM
  • 1. I refer the honorable gentleman to my first reply posted some minutes ago.

    2. Please read the following post to set your expectations:

    This forum is for scripting questions rather than script requests


    -- Bill Stewart [Bill_Stewart]

    Thursday, June 28, 2018 3:17 PM
    Moderator
  • please try to use new script version: https://gallery.technet.microsoft.com/Windows-Unquoted-Service-190f0341

    original script contain whatif key and should not change anything - only display, but if you remove whatif at last string it shoul work

    please, test this script before executing in production, it was tested only on 2 laptops (I have not more, right now)


    The opinion expressed by me is not an official position of Microsoft

    • Marked as answer by Chrism88 Thursday, September 27, 2018 10:43 AM
    Sunday, July 15, 2018 10:13 PM
  • You need backslashes in your Registry paths:

    $BaseKeys = "HKLM:\System\CurrentControlSet\Services", #Services
    

    Keith


    Keith

    Sunday, July 15, 2018 11:08 PM
  • I fixed about 20 errors and gave up.  YOU need to take time to actually learn PowerSHell.

    This is as far as I care to go.

    $BaseKeys = @(
        'HKLM:\System\CurrentControlSet\Services', #Services
        'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall', #32bit Uninstalls
        'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' #64bit Uninstalls
    )
    #Blacklist for keys to ignore
    $BlackList = $Null
    #Create an ArrayList to store results in
    $Values = New-Object System.Collections.ArrayList
    
    
    #Discovers all registry keys under the base keys
    $DiscKeys = Get-ChildItem -Recurse -Directory $BaseKeys -Exclude $BlackList -ErrorAction SilentlyContinue |
            Select-Object -ExpandProperty Name |
            ForEach-Object{
                ($_.ToString().Split('') | 
                    Select-Object -Skip 1) -join ''
            }
    
    $Registry = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')
    
    foreach ($RegKey in $DiscKeys){
        
        Try {
            $ParentKey = $Registry.OpenSubKey($RegKey, $True)
        }
        Catch {
            Write-Debug "Unable to open $RegKey" 
        }
        
        #Test if registry key has values
        If ($ParentKey.ValueCount){
            $MatchedValues = $ParentKey.GetValueNames() | ?{ $_ -eq "ImagePath" -or $_ -eq "UninstallString" }
            ForEach ($Match in $MatchedValues){
                
                #RegEx that matches values containing .exe with a space in the exe path and no double quote encapsulation
                $ValueRegEx = '(^(?!u0022).*s.*.[Ee][Xx][Ee](?< !u0022))(.*$)' 
                $Value = $ParentKey.GetValue($Match)
                
                #Test if value matches RegEx
                If ($Value -match $ValueRegEx) { 
                    
                    $RegType = $ParentKey.GetValueKind($Match)
                    
                    #Uses the matches from the RegEx to build a new entry encapsulating the exe path with double quotes
                    $Correction = "$([char]34)$($Matches[1])$([char]34)$($Matches[2])"
                    
                    #Attempt to correct the entry
                    Try { 
                        $ParentKey.SetValue($Match, $Correction, [Microsoft.Win32.RegistryValueKind]::$RegType) 
                    } 
                    Catch {
                        Write-Debug "Unable to write to $ParentKey"
                    }
                    
                    #Add a hashtable containing details of corrected key to ArrayList
                    $hash = [pscustomobject]@{
                        Name = $Match
                        Type = $RegType
                        Value = $Value
                        Correction = $Correction
                        ParentKey = "HKEY_LOCAL_MACHINE$RegKey" 
                    }
                    $Values.Add($hash)
                    $ParentKey.Close()
                }
    
                $Registry.Close() 
                $Values | Select-Object ParentKey,Value,Correction,Name,Type

    Notice you are missing closures and other things.


    \_(ツ)_/


    • Edited by jrv Monday, July 16, 2018 12:12 AM
    Monday, July 16, 2018 12:07 AM
  • my guess that script was found here: 

    https://www.tecklyfe.com/remediation-microsoft-windows-unquoted-service-path-enumeration-vulnerability/amp/

    on that site missed 50% special charakters but there also exist correct link ;-)


    The opinion expressed by me is not an official position of Microsoft

    Monday, July 16, 2018 6:34 AM
  • here is a link to the fix, please like and subscribe.

    https://www.youtube.com/watch?v=whIIK6OGkoc

    works perfect :-)

    Sunday, January 13, 2019 9:20 PM