From 30baf5e70e215475831651a938241e1372b9eeb3 Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Mon, 4 May 2026 10:52:17 -0400 Subject: [PATCH] Fix: Read session user certs from registry, not process identity - Cert:\CurrentUser resolves to PROCESS identity, not session user - Now reads directly from HKEY_USERS\{SID}\Software\Microsoft\SystemCertificates\ - Parses certificate blobs from Root and CA store registry keys - Only attempts if CurrentUserSession is available and hive is loaded - Skips invalid certificate blobs gracefully --- Invoke-OpenSSHConfiguration.ps1 | 71 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/Invoke-OpenSSHConfiguration.ps1 b/Invoke-OpenSSHConfiguration.ps1 index 86b1f73..add746b 100644 --- a/Invoke-OpenSSHConfiguration.ps1 +++ b/Invoke-OpenSSHConfiguration.ps1 @@ -482,7 +482,9 @@ Switch (Test-ProcessElevationStatus) $CertificateStorePathList.Add('Cert:\LocalMachine\Root') $CertificateStorePathList.Add('Cert:\LocalMachine\CA') - #Include CurrentUser CA stores (use logged-in user's store if running as SYSTEM) + #Include CurrentUser CA stores from session user (not process user) + #Note: Cert:\CurrentUser resolves to PROCESS identity, not session user + #To access session user's certs, we read directly from HKEY_USERS\{SID} $UserCertificates = New-Object -TypeName 'System.Collections.Generic.List[System.Security.Cryptography.X509Certificates.X509Certificate2]' Switch (($Null -ine $CurrentUserSession) -and ([System.String]::IsNullOrEmpty($CurrentUserSession.SID) -eq $False)) @@ -490,51 +492,60 @@ Switch (Test-ProcessElevationStatus) {($_ -eq $True)} { #Check if user's registry hive is loaded under HKEY_USERS - $UserRegistryPath = "Registry::HKEY_USERS\$($CurrentUserSession.SID)" + $UserRegistryBasePath = "Registry::HKEY_USERS\$($CurrentUserSession.SID)" - Switch (Test-Path -Path $UserRegistryPath -ErrorAction SilentlyContinue) + Switch (Test-Path -Path $UserRegistryBasePath -ErrorAction SilentlyContinue) { {($_ -eq $True)} { - $WriteLogMessage.Invoke(0, @("Accessing certificate store for user: $($CurrentUserSession.NTAccount) [SID: $($CurrentUserSession.SID)]")) + $WriteLogMessage.Invoke(0, @("Accessing certificate store for session user: $($CurrentUserSession.NTAccount) [SID: $($CurrentUserSession.SID)]")) - #Open user's Root and CA stores via X509Store - $UserStoreLocations = @( - @{Name = 'Root'; Location = [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser} - @{Name = 'CA'; Location = [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser} - ) + #Read certificates directly from user's registry hive + $UserCertStoreNames = @('Root', 'CA') - ForEach ($StoreInfo In $UserStoreLocations) + ForEach ($StoreName In $UserCertStoreNames) { - Try + $UserCertRegistryPath = "$($UserRegistryBasePath)\Software\Microsoft\SystemCertificates\$($StoreName)\Certificates" + + Switch (Test-Path -Path $UserCertRegistryPath -ErrorAction SilentlyContinue) { - $UserCertStore = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Store' -ArgumentList @($StoreInfo.Name, $StoreInfo.Location) - $UserCertStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly -bor [System.Security.Cryptography.X509Certificates.OpenFlags]::OpenExistingOnly) - $UserCertificates.AddRange($UserCertStore.Certificates) - $UserCertStore.Close() - } - Catch - { - $WriteLogMessage.Invoke(1, @("Unable to access user certificate store `"$($StoreInfo.Name)`": $($_.Exception.Message)")) + {($_ -eq $True)} + { + $CertSubKeys = Get-ChildItem -Path $UserCertRegistryPath -ErrorAction SilentlyContinue + + ForEach ($CertSubKey In $CertSubKeys) + { + Try + { + $CertBlob = Get-ItemProperty -Path $CertSubKey.PSPath -Name 'Blob' -ErrorAction SilentlyContinue + + Switch ($Null -ine $CertBlob.Blob) + { + {($_ -eq $True)} + { + $X509Cert = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2' -ArgumentList @(,[System.Byte[]]$CertBlob.Blob) + $UserCertificates.Add($X509Cert) + } + } + } + Catch + { + #Skip invalid certificate blobs + } + } + } } } + + $WriteLogMessage.Invoke(0, @("Found $($UserCertificates.Count) certificate(s) in session user's store.")) } Default { - $WriteLogMessage.Invoke(1, @("User registry hive not loaded for SID: $($CurrentUserSession.SID). Using current process identity certificates.")) - $CertificateStorePathList.Add('Cert:\CurrentUser\Root') - $CertificateStorePathList.Add('Cert:\CurrentUser\CA') + $WriteLogMessage.Invoke(1, @("User registry hive not loaded for SID: $($CurrentUserSession.SID). Skipping user certificates.")) } } } - - Default - { - #No user session info available, use current process identity - $CertificateStorePathList.Add('Cert:\CurrentUser\Root') - $CertificateStorePathList.Add('Cert:\CurrentUser\CA') - } } $CACertificates = New-Object -TypeName 'System.Collections.Generic.List[System.Security.Cryptography.X509Certificates.X509Certificate2]' @@ -550,7 +561,7 @@ Switch (Test-ProcessElevationStatus) } } - #Add user certificates (already filtered by store type) + #Add user certificates (filter for CA certs) Switch ($UserCertificates.Count -gt 0) { {($_ -eq $True)}