Certificate Store Backup and Cleanup (With a Little Powershell)

I was thinking about HTTPS packet inspection the other day.  The type of HTTPS packet inspection that could be performed with a product such as Forefront Threat Management Gateway, for instance.  Basically, you start by funneling everyone's network traffic through your gateway.  Second, you install an SSL certificate into the Trusted Root CA certificate store on all of the client computers whose encrypted traffic you wish to inspect. Now, your gateway is ready to act as a "man-in-the-middle" and decrypt everyone's outbound traffic.  Traffic to their personal email accounts on Gmail and Hotmail... traffic to their online banking websites... transparently, without their knowledge.

I.T. departments do this to their employees all the time.  But I wonder... if it's so easy for I.T. departments, what would stop something like a government agency from installing this same sort of gateway in an ISP datacenter, and sniffing everyone's HTTPS traffic?

If only the government had some way of getting a trusted CA certificate into the cert store on everyone's computer...


So anyway, this thought led me to think about cleaning up my own certificate stores on my personal machines.  We trust so many certificates by default, and we don't really know what they all are or where they came from.  Most of us who use Windows just rely on Microsoft's Windows Root Certificate Program to tell us which root CAs we should trust by default.

So first, we need to turn off Automatic Root Certificates Update via Group Policy (if you administer an Active Directory domain) or via local security policy if you are on a standalone PC:

Computer Configuration > Administrative Templates > System > Internet Communication settings > Turn off Automatic Root Certificates Update


If you leave this setting turned on, Windows will use the internet to re-download and replace any root CA certificates that it thinks you should trust.  So you'll delete them, and they'll just reappear.

Secondly, there are many certificates in your certificate stores for a reason.  Many of them are there for verifying signed code, such as kernel drivers, for example. If Windows cannot verify their digital signatures, they won't load. Windows might not even boot properly.  Nevertheless, Microsoft continues to ship some very old certificates with Windows, such as these:


They're there for "backwards compatibility," of course.  I decided I'd take the risk that I didn't need certificates from the 20th century anymore, and figured I would delete them.

Then there's this guy:


On the list of organizations that engender warm, fuzzy feelings of implicit trust, this one is pretty much at the rock bottom of that list... right above the Nigerian pirate running a CA on his laptop.  Nevertheless, this is one of those root certificate authority certs that is protected and automatically distributed by the Windows Root CA Program.  But since we've disabled the automatic certificate update, and I don't feel like I should be compelled to trust this certificate authority, it's time to delete it.

But, one last thing before we delete the certificates.  Let's make a backup of all of our certificate stores, so that if we accidentally delete a certificate that's required for something important, we can restore it.  It took about 15 minutes of Powershell to write the backup script.  With another 5 minutes, you could sprinkle a little decoration on it and make a cmdlet out of it.

# Backup-CertificateStores.ps1
Set-StrictMode -Version Latest
[String]$CertBackupLocation = "C:\Users\Ryan\Documents\CertStoreBackup_$([Environment]::MachineName)\"

If (-Not (Test-Path $CertBackupLocation))
    { New-Item $CertBackupLocation -ItemType Directory | Out-Null }

$AllCerts = Get-ChildItem Cert:\ -Recurse | Where PSIsContainer -EQ $False

Foreach ($Cert In $AllCerts)
{
    [String]$StoreLocation = ($Cert.PSParentPath -Split '::')[-1]    
    If (-Not (Test-Path (Join-Path $CertBackupLocation $StoreLocation)))
        { New-Item (Join-Path $CertBackupLocation $StoreLocation) -ItemType Directory | Out-Null }

    If (-Not $Cert.HasPrivateKey -And -Not $Cert.Archived)
    {
        Export-Certificate -Cert $Cert -FilePath ([String](Join-Path (Join-Path -Path $CertBackupLocation $StoreLocation) $Cert.Thumbprint) + '.crt') -Force
    }
}

Now you have backups of all your public certificates (this doesn't back up your private certs or keys,) so delete whichever ones you feel are unnecessary.

Comments are closed