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
This commit is contained in:
GraceSolutions
2026-05-04 10:52:17 -04:00
parent 903d87acf4
commit 30baf5e70e
+41 -30
View File
@@ -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)}