1. Einleitung
     
  2. Zertifikatsverwaltung
    2.1 .Net Namespace "System.Security.Cryptography.X509Certificates"
          2.1.1 X509Certificate2-Klasse
                   2.1.1.1 Ein X509Certificate2-Object erstellen
                               Beispiel 1a: Auslesen der Zertifikate im lokalen Store mittels dem Zertifikatsprovider
                               Beispiel 1b: Auslesen der Zertifikate im lokalen Store mittels der .Net-Klasse X509Store
                               Beispiel 2a: Ein Zertifikatsobjekt aus einer lokalen pfx-Zertifikatsdatei erstellen (Import-Methode)
                               Beispiel 2b: Ein Zertifikatsobjekt aus einer lokalen pfx-Zertifikatsdatei erstellen (cmdlet: get-pfxcertificate)
                    2.1.1.2 Anwendungen von X509Certificate2
                               Beispiel 1: Anwenden von Eigenschaften und Methoden auf ein Zertifikatsobjekt
                               Beispiel 2: Zertifikat aus *.cer Datei importieren und Eigenschaften auslesen
          2.2.2 X509Store-Klasse     
                   Beispiel 1: Mehrere Klassen des System.Security.Cryptography.X509Certificates-Namespaces im Einsatz
          2.2.3 Sonstige .Net Klassen
                   Beispiel 1a: Exportieren eines Zertifikats in eine pfx-Datei (Klasse X509ContentType)
                   Beispiel 1b: Exportieren aller Zertifikats aus dem Currentuser\my-Store in pfx-Dateien (Klasse X509ContentType)
    2.3 Zertifikatsverwaltung mit dem Zertifikatsprovider
    2.4 Zertifikatsverwaltung mit dem Quest QAD-SnapIn
          Beispiel 1: Auflisten von Zertifikaten mit QAD (Storelocation: LocalMachine, Store: My)
          Beispiel 2: Anzeigen aller Zertifikate im LocalMachineStore
          Beispiel 3a Anlage eines zusätzlichen Zertifikatsstores für den "aktuellen Benutzer" mit QAD
          Beispiel 3b: Löschen eines zusätzlichen Zertifikatsstores für den "aktuellen Benutzer" mit QAD
          Beispiel 4: Exportieren aller Zertifikats aus dem Currentuser\my-Store in pfx-Dateien
          Beispiel 5: Ein Zertifikatsobjekt mit einem Quest-cmdlet erstellen
     

3.   Praktische Anwendungen

3.1 Untrusted Certificates
 

4 Microsoft Trusted Root Certificate Program
4.1 Automatic Root Certificate Update 
4.1.1 Funktionsweise des Update Root Programs
4.1.2 Alternativen zum Update Root Program
4.1.3 Zertifkatscontainer der unterschiedlichen Quellen am Client
4.2 Untrusted Certificates

 

 

1 Einleitung

Eine gute Einführung in die Arbeitsweise von Zertifikaten findet man hier: Technet: How Certificate Services Works


Unter diesem Kapitel möchte ich erarbeiten, wie man Informationen aus Zertifikaten lesen kann, Zertifikate monitort oder diese im- und exportiert. Dazu gehören detaillierte Fragen wie

- haben meine Rechner die richtigen Zertifikate im richtigen Zertifikatsstore
- sind diese Zertifikate gültig
- wann laufen die Zertifikate ab
- sind Zertifikate gesperrt
- ist die Zertifikatskette überall vorhanden
- welche Fileformate soll man für welchen Einsatzzweck wählen

Viele dieser Aufgaben erledigen sich im Zusammenspiel mit einer in ein ActiveDirectory integrierten Zertifizierungsstelle und der Verwendung von GroupPolicies quasi von alleine. Möchte man aber die Verantwortung einer Zertifizierungsstelle nicht im eigenen Hause tragen, oder kommt über Wirtschaftlichkeitsberechnungen zu dem Schluss sich seine Zertifikate lieber von einer externen CA zu besorgen, so können Powershell und .Net wertvolle Werkzeuge für die Administration und das Monitoring der Zertifikate sein.


Eine Alternative zur manchmal etwas aufwändigen .Net-Schreibweise für dieses Aufgabenspektrum ist der Einsatz der
Quest Software: Free PowerShell Commands for Active Directory

Dabei handelt es sich um ein kostenloses SnapIn, das unter anderem für den Bereich "X.509 Certificate Management" eine Reihe interessanter cmdlets mitbringt. Einige der Beispiele in diesem Kapitel setzen die Installation dieses SnapIns voraus. Module und SnapIns allgemein habe ich in diesem Kapitel unter "My Powershell" näher erläutert .

Alle cmdlets des SnapIns hat Quest im Adminguide "ActiveRoles_MgmtShellForAD_14_AdminGuide_English.pdf" dokumentiert, der unter dem obigen Questlink downloadbar ist.
Für die "PKI cmdlets" gibt es nocheinmal ein Extra Paper, für das sich der Download durchaus lohnt. Quest Software: Guide for Using Quest AD-PKI cmdlets
Der Guide umfasst etwa 50 Seiten und gibt in der ersten Hälfte eine meiner Meinung nach sehr gute Einführung über Zertifikate und behandelt im zweiten Teil die PKI-cmdlets.
 

2 Zertifikatsverwaltung

2.1 .Net Namespace "System.Security.Cryptography.X509Certificates"

MSDN: System.Security.Cryptography.X509Certificates-Namespace

Unter diesem Namespace sind alle Klassen enthalten, die für die .Net -Programmierung mit Zertifikaten benötigt werden
 

2.1.1 X509Certificate2-Klasse

MSDN: X509Certificate2 Class

Möchte man mit bestimmten X509-Zertifikaten arbeiten, so benötigt man aus dem "System.Security.Cryptography.X509Certificates Namespace" entweder die Klasse "X509Certificate" oder "X509Certificate2". Beide Klassen stellen X509-Zertifikat dar und beinhalten Methoden und Eigenschaften für den Umgang mit Zertifikaten.

Die MSDN nennt als hauptsächlichen Unterschied beider Klassen:

"The primary difference between the X509Certificate and the X509Certificate2 class is that the private key must reside in the certificate store for the X509Certificate class."

In diesem Kapitel 2.1.1 und seinen Unterkapiteln kümmere ich mich nur um die Klasse X509Certificate2!
 

2.1.1.1 Ein X509Certificate2-Object erstellen

Powershell bringt auch in der Version 2 nur wenige cmdlets mit, mit denen ein gewohnt einfacher und komfortabler Umgang mit Zertifikaten möglich wäre. Um Objekte der Klasse "X509Certificate2" zu erzeugen, stehen damit folgende Werkzeuge zur Verfügung:

  • Zertifikatsprovider
  • .Net Klassen
  • Powershell cmdlet "Get-PfxCertificate"

Anbei einige Beispiele, die verdeutlichen sollen, wie mit den eben genannten Werkzeugen Zertifikatsobjekte erzeugt werden können.

Beispiel 1: Auslesen der Zertifikate aus dem lokalen Store 

Clear-Host

Set-StrictMode -Version "2.0"

 

$Certs = @(GCI cert:/localmachine/my)
$Certs[0] | Format-List Serialnumber,NotAfter,NotBefore
$Certs[0].GetType() | Format-Table Name,BaseType -Auto

#mögliche Ausgabe

 

SerialNumber : 4F6AB3D50008007F3508

NotAfter     : 01.11.2013 10:05:47
NotBefore    : 05.05.2015 11:05:47
 
Name             BaseType                                                     
----             --------                                                     
X509Certificate2 System.Security.Cryptography.X509Certificates.X509Certificate


Anmerkung: Die Syntax des Zertifikatsprovider ist sicherlich die einfachste. Sein Nachteil liegt in der Beschränkung auf die Stores der lokalen Maschine. Möchte man auf die Stores von anderen Maschinen zugreifen, ist der direkte, aber etwas aufwändigere Aufruf der .Net-Klasse der richtige Ansatz (siehe nächstes Beispiel).

Mit der Funktion GetType() bekommt ihr den Namen der Klasse "X509Certificate2 angezeigt

 

Beispiel 2: Auslesen der Zertifikate lokalen oder remote Store mittels "X509Store"

Clear-Host
Set-StrictMode -Version "2.0"
 
$Certs=@()
$HostName = "PC01"
$X509Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("\\$HostName\My","LocalMachine")
$X509Store.Open("ReadOnly")
$Certs = $X509Store.Certificates
$Certs[0] | Format-List Serialnumber,NotAfter,NotBefore
$Certs[0].GetType() | Format-Table Name,BaseType -Auto
#Ausgabe identisch zu Beispiel 1

Der Vorteil des folgenden Beispiels gegenüber dem vorigen Beispiel 1) liegt hier in der Remotefähigkeit.

MSDN: X509Store-Konstruktor (StoreName, StoreLocation)


Beispiel 3: Ein Zertifikatsobjekt aus einer lokalen pfx-Zertifikatsdatei erstellen (X509Certificates2 - Import() )

Clear-Host
Set-StrictMode -Version "2.0"
 
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2    
$PfxPass = "Password123" 
$CertPath = "H:\Zertifikate\certs\MD165-private.pfx"   
$Cert.Import($CertPath,$PfxPass,"Exportable,PersistKeySet")
 
$Cert | FL *
$Cert.GetType() | Format-Table Name, BaseType -auto 
#Ausgabe identisch zu Beispiel 1

MSDN: X509Certificate2.Import-Methode (String)

die Import()-Methode "füllt ein X509Certificate2-Objekt mit Informationen aus einer Zertifikatsdatei auf."

 

Beispiel 4: Ein Zertifikatsobjekt aus einer lokalen pfx-Zertifikatsdatei erstellen (cmdlet: get-pfxcertificate)

siehe Technet: Get-PfxCertificate

Clear-Host
Set-StrictMode -Version "2.0"
 
$CertPath = "H:\Zertifikate\certs\MD165-private.pfx"   
$Cert = Get-PfxCertificate -FilePath $CertPath

#Ausgabe identisch zu Beispiel

Get-PfxCertificate besitzt keinen Passwortparameter.


Zusammenfassung Beispiele 1 bis 4:
Wie man an der identischen Ausgabe des Typs der Beispiele sieht, enthält die Variable $Cert ein X509-Zertifikatsobject (X509Certificate2. Dieses Zertifikatsobjekt kann mit einer ganzen Reihen von Eigenschaften und Methoden der X509Certificate2-Klasse behandelt werden.
Das nachfolgende Kapitel 2.1.1.2 zeigt noch ein paar Möglichkeiten die Objekte weiter zu behandeln.

MSDN: X509Certificate2-Konstruktor (String, SecureString, X509KeyStorageFlags)

MSDN: X509KeyStorageFlags-Enumeration

Ein weiteres ausgearbeitetes Beispiel: Technet Scripting Guys: Use PowerShell and .NET to Find Expired Certificates
 

2.1.1.2 Methoden und Eigenschaften für X509Certificate2

Beispiel 1: GetIssuername(), NotAfter, Verify() 

Clear-Host
Set-StrictMode -Version "2.0"
 
$Cert = @()
$Cert = (GCI cert:/localmachine/my | Select -First 1) 
$Cert.GetIssuerName()  #Methode
$Cert.Issuer  #Methode
$Cert.NotAfter #Eigenschaft
$Cert.Verify() #Methode
  • GetIssuerName():  liefert den Namen der Zertifizierungsstelle ab, die das X.509-Zertifikat (v.3) ausgestellt hat
  • Verify():  Führt mithilfe von Basisvalidierungsrichtlinien eine Validierung von X.509-Ketten
  • Notafter: Ruft das Datum in Ortszeit ab, ab dem ein Zertifikat nicht mehr gültig ist
     

weitere Eigenschaften und Methoden unter: 

MSDN:  X509Certificate2-Klasse

 

Beispiel 2: Eigenschaften eines Zertifikates aus einer *.cer Datei 

In der MSDN befindet sich ein Visualbasic-Programmcode, den ich hier nach Powershell konvertieren möchte. Dieser Code zeigt meiner Meinung nach schön die Möglichkeiten der X509Certificate2 Klasse auf
Der orginal VB-Code befindet sich am Ende des Artikels unter MSDN: X509Certificate2.Version Property

Clear-Host
Set-StrictMode -Version "2.0"
 
Function Main{
  $CertPath = "H:\certs\MD165.cer"
  Show-CertInfo -Filename $CertPath
} #end Function
 
Function Read-File{
# Einlesen eines Zertifikatfiles in ein Bytearray
    Param($FileName)
    $FileStream = New-Object System.IO.FileStream ($FileName,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)
    [Int]$Size = [Math]::Truncate($FileStream.Length)
    [Byte[]] $Data = New-Object Byte[] $Size
    $FileStream.Read($Data, 0, $Size) | Out-Null
    Return $Data
}#end Function
 
Function Show-CertInfo{
    Param($Filename)
    $X509 = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2   
    [Byte[]] $RawData = Read-File -Filename $Filename
    # 'Create X509Certificate2 object from .cer file.
    $X509.Import($RawData)
    #http://msdn.microsoft.com/en-us/library/ms148437.aspx
    #X509Certificate2.Import Method (Byte())
 
    "Subject: {1}{0}" -f [Environment]::NewLine,$x509.Subject
    "Issuer: {1}{0}" -f [Environment]::NewLine, $x509.Issuer
    "Version: {1}{0}" -f [Environment]::NewLine, $x509.Version
    "Valid Date: {1}{0}" -f [Environment]::NewLine, $x509.NotBefore
    "Expiry Date: {1}{0}" -f [Environment]::NewLine, $x509.NotAfter
    "Thumbprint: {1}{0}" -f [Environment]::NewLine, $x509.Thumbprint
    "Serial Number: {1}{0}" -f [Environment]::NewLine, $x509.SerialNumber
    "Friendly Name: {1}{0}" -f [Environment]::NewLine, $($($x509.PublicKey).Oid).FriendlyName
    "Public Key Format: {1}{0}" -f [Environment]::NewLine, $($($x509.PublicKey).EncodedKeyValue).Format($True)
    "Raw Data Length: {1}{0}" -f [Environment]::NewLine, $RawData.Length
    #"Certificate to string: {1}{0}" -f [Environment]::NewLine, $x509.ToString($True)
    #"Certificate to XML String: {1}{0}" -f [Environment]::NewLine, $($($x509.PublicKey).Key).ToXmlString($False)
   
    #Add the certificate to a X509Store.
    $Store = New-Object System.Security.Cryptography.X509Certificates.X509Store
    $Store.Open("MaxAllowed")
    $Store.Add($X509)
    $Store.Close()
}#end Function
 
Main
#Ausgabe

Subject: CN=Karl Napf, CN=Users, DC=Dom1, DC=intern

Issuer: CN=Dom1-CA01, DC=Dom1, DC=intern

Version: 3

Valid Date: 13.05.2011 14:57:07

Expiry Date: 12.05.2012 14:57:07

Thumbprint: CFAC05F46158ABB0BC29D5EC30E10C06B9655B3F

Serial Number: 74E4644900000000005D

Friendly Name: RSA

Public Key Format: 30 82 01 0a 02 82 01 01 00 a8 dc b2 40 ed 27 4f 7d 19 bb 8e af 81 db bd 89 d4 e7 62 50 62 06 aa ec b9 7b 0a b3 73 71 58 1a 96 a3 e1 5e d8 11 f4 e5 c5 9e  80 24 93 4f 57 65 5a 3c 26 9a ce 80 06 9c 4d a0 59 6c 7c 80 5a d3 c7 e7 09 06 df 17 6b 1f b6 94 cf 9b 8a 28 5b 65 b8 28 31 62 54 4e 38 be c5 cc 14 f6 ca 1f e0 2e 4b 66 ac  24 d6 fe 03 75 0c 4c 68 6e c8 d2 7e e5 b8 f8 77 1c 67 18 98 55 a7 49 fa 51 fc e2 a1 ea 5b b6 73 d3 fe 00 91 88 df 81 66 f7 12 e6 9e 70 fa fe a3 79 31 ff ff 87 42 eb 34 9b  af 1b 0e 5e 17 45 5c 5b 1e 40 28 09 da 53 6d 83 09 95 1a 72 6e 91 c8 97 8a a5 91 f5 81 5b ea 58 8a 37 e3 ce a7 77 2f d9 70 86 22 70 cb c0 16 d9 69 6f a6 5e 16 f0 b9 5e c7  b9 6c 1b 06 08 42 e5 9b ad 60 b4 f9 99 59 4b 7b 38 14 70 61 4c ea 33 de c0 fc f1 3a cf c5 1f 6c 08 85 c9 15 0a 03 fe f4 93 f6 59 02 03 01 00 01

Raw Data Length: 2094

Steht kein Cer-Zertifikatsfile zur Verfügung, kann man sich einfach in der MMC -> Zertifikate (certmgr.msc) aus dem Container "Vertrauenswürdige Stammzertifizierungsstellen" ein paar Zertifikate mit "Alle Aufgaben -> Exportieren" exportieren. Dabei ist es egal, ob man als Format DER oder BASE-64 wählt.

Das Beispiel liest in der Function "readfile" eine Zertifikatsdatei im cer-Format in ein Bytearray ein. In der Function "showCertInfo" wird ein das Objekt $x509 aus der Klasse "X509Certificate2" erzeugt und mit der import-Methode mit den Daten aus dem Bytearray befüllt.
Anschliessend werden einige Eigenschaften des Objekts $X509 ausgelesen und ausgegeben.

weitere Links:

Zum Thema "ByteArray" siehe "Zertifikate -> Allgemeines -> 3.2 ByteArrays"
Zum Thema "Formatierung" siehe "Formatierung des Outputs -> 1 Schnelleinstieg in die Formatierung"
 

2.2.2 X509Store-Klasse

MSDN: X509Store-Klasse

Unter den eben genannten MSDN-Link findet man wieder ein ausführliches Beispiel in VisualBasic zu den Klassen

 

  • X509Store
  • X509Certificate2
  • X509Certificate2Collection

Dieses MSDN- Beispiel möchte ich ebenfalls nach Powershell konvertieren.


Beispiel 1: Mehrere Klassen des System.Security.Cryptography.X509Certificates-Namespaces im Einsatz

#1
#Create new X509 store called teststore from the local certificate store.
$storename = "teststore"
$storelocation = "Currentuser"
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store($storename,$storelocation)
$store.Open("ReadWrite")

#2
#Create certificates from certificate files.
$certificate1 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\mycerts\zert1.cer")
$certificate2 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\mycerts\zert2.cer")
$certificate5 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\mycerts\zert5.cer")

#3
#Create a collection and add two of the certificates.
$collection =  New-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$collection.Add($certificate2)
$collection.Add($certificate5)
      
#4
#Add certificates to the store.
$store.Add($certificate1)
$store.AddRange($collection)

$storecollection = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$storecollection=$store.certificates

"Store name: {0}" -f $store.Name
"Store location: {0}" -f $store.Location
$x509 =new-object System.Security.Cryptography.X509Certificates.X509Certificate2
foreach($x509 in $storecollection){
     $x509.subject
     #$storecollection | %{$_.subject #Alternativ
}

#5
#Remove a certificate
$store.Remove($certificate1)
$storecollection2 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$storecollection2=$store.certificates
"{1}Store name: {0}" -f $store.Name, [Environment]::NewLine
$x509a =new-object System.Security.Cryptography.X509Certificates.X509Certificate2
foreach($x509a in $storecollection2){
   $x509a.subject
   #$storecollection | %{$_.subject #alternativ zu foreach
}

#6
#Remove a range of certificates.
$store.RemoveRange($collection)
$storecollection3 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
$storecollection3=$store.certificates
"{1}Store name: {0}" -f $store.Name, [Environment]::NewLine
If ($storecollection3.Count -eq 0) {
   "Store contains no certificates."
}Else{
   $x509b =new-object System.Security.Cryptography.X509Certificates.X509Certificate2
   foreach($x509b in $storecollection3){
       $x509b.subject
       #$storecollection3 | %{$_.subject #alternativ zu foreach
       } #foreach
} #Endif

#Step 7
#Close the store.
$store.Close()

Stehen keine Cer-Zertifikatsfiles zur Verfügung, kann man sich einfach in der MMC -> Zertifikate (certmgr.msc) aus dem Container "Vertrauenswürdige Stammzertifizierungsstellen" ein paar Zertifikate mit "Alle Aufgaben -> Exportieren" exportieren. Dabei ist es egal, ob man als Format DER oder BASE-64 wählt.

Anmerkungen zum Code:

Zu 1)
- Im Kapitel Allgemeines -> 2 CertificateLocation/ CertificateStore habe ich einige kurze Beispiele aufgelistet, wie mit der X509Store-Klasse Zertifikatstores behandelt werden können.
- lautet  $storelocation nicht "currentuser", sondern "localmachine", so kann mit $storename = "\\dom1dc01\teststore" auch ein Store auf einer Remotemaschine angelegt werden.
- Die Klasse X509Store ist überladen mit mehreren Konstruktoren. Das Beispiel nutzt den Konstruktor mit dem Parametern Storelocation und des Storenamens. MSDN: X509Store-Konstruktor (StoreName, StoreLocation)

- Die möglichen Flags der Openmethode findet man  unter MSDN: OpenFlags-Enumeration
 

Zu 2)
Hier werden aus *.cer Files Objekte der Klasse X509Certificate2 erstellt. *.cer zeichnen sich dadurch aus, daß Sie keinen privaten Schlüssel besitzen.
Für X509Certificate2-Objekte mit privatem Schlüssel und Passwort muß die Import-Methode zusätzlich benützt werden. Der Import eines Zertifikats aus einer *.pfx Datei (= Zertifikate mit privatem Schlüssel) ist in Beispiel 3 unter 2.1.1.1 Ein X509Certificate2-Object erstellen beschrieben
 

Zu 3)  
MSDN:  X509Certificate2Collection-Klasse

Die Klasse X509Certificate2Collection erstellt ein Array, dessen Elemente einzelne Zertifikate der Klasse X509Certificate2 sind. Mit der Add-Methode werden Zertifikate am Ende des Arrays hinzugefügt

#Codeergänzung
$collection.count
$collection[1].gettype() | Format-Table Name,BaseType -auto
#Ausgabe
2

Name             BaseType                                                    
----             --------                                                    
X509Certificate2 System.Security.Cryptography.X509Certificates.X509Certificate

Zu 4)  
- dem in Step 1) erzeugten Objekt $store der Klasse X509Store einige Zertifikatsobjekte hinzugefügt, einmal als einzelnes Zertifikat ($certificate1) und einmal als Range ($Collection bzw. $certificate2 und $certificate5).
- die X509Name- und X509Location-Eigenschaft des $StoreObjects werden ausgegeben.

Zu 5)  
Aus dem Objekt $StoreCollection2 wird ein einzelnes Zertifikat entfernt.


Zu 6)
Aus dem Objekt $StoreCollection§ wird ein ein Zertifikatrange ($collection) entfernt.
 

2.2.3 Sonstige .Net Klassen

Beispiel 1a: Exportieren eines Zertifikats in eine pfx-Datei (Klasse X509ContentType)

Im Beispiel 1c des Kapitels 2.1 Überblick der verschiedenen Heransgehensweisen ..,  haben wir gesehen, wie man Zertifikate aus einer pfx-Datei importiert. Auch der umgekehrte Weg ist natürlich möglich, also ein Zertifikat etwa aus dem My-Store in eine pfx-Datei zu exportieren. Voraussetzung für den Export eines Zertifikats in eine pfx-Datei ist, daß im my-Store auch der private Schlüssel des Zertifikats gespeichert ist und dieser Schlüssel als exportierbar markiert ist.

$cert=@()
$cert = (dir cert:\currentuser\my)[0]
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::pfx
$pass = ConvertTo-SecureString "Hurra" -AsPlainText -Force
$bytes = $cert.export($type, $pass)
System.IO.File]::WriteAllBytes("c:\mycerts\file.pfx", $bytes)

#aus TechNet Blogs > My Nuggets > exporting certificate from user store to PFX using powershell  

Diesen Code habe ich in der Technet hier gefunden.

Der Import eines Zertifikats aus einer *.pfx Datei ist in Beispiel 3 unter 2.1.1.1 Ein X509Certificate2-Object erstellen beschrieben

 

Beispiel 1b: Exportieren aller Zertifikats aus dem Currentuser\my-Store in pfx-Dateien (Klasse X509ContentType)

$Certs=@()
$certs = (dir cert:\currentuser\my)
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::pfx
$pass = ConvertTo-SecureString "Hurra" -AsPlainText -Force
$certs | % {
   $bytes = $_.export($type, $pass)
   if ($_.hasprivatekey){ #nur Zertifikate mit PrivatKey exportieren
      [System.IO.File]::WriteAllBytes("c:\mycerts\$($_.subject).pfx", $bytes)
      }else{
      "{0} hat keinen Privatekey und kann daher nicht in eine pfx-Datei exportiert werden" -f $_.subject
      }
   }

Der Code exportiert alle Zertifikate mit privatem Schlüssel in das Verzeichnis c:\mycerts. Leider lässt sich nicht steuern, ob alle Zertifikate der Zertifikatskette ebenfalls exportiert werden sollen. Anwendungen, die diese Kette benötigen, kommen mit den so erzeugten PFX-Files leider nicht zurecht.

Mehr Details zum PKCS#12 Standard gibt es unter: RSA LaboratoriesPKCS #12: Personal Information Exchange Syntax Standard

Dieselbe Lösung erreicht man auch über das Quest Active Roles cmdlets "Export-QADCertificate", wie in Beispiel 4 unter 2.4 Zertifikatsverwaltung mit dem Quest QAD-SnapIn gezeigt. Der Einsatz des Export-QADCertificate ist weniger kryptisch, als die Programmierung mit .Net
 

2.3 Zertifikatsverwaltung mit dem Zertifikatsprovider

Technet: Certificate Provider

Wie schon weiter oben beschrieben, bietet der Certificate Provider eine einfache Syntax an, um Objekte der Klasse X509Certificate2 zu erstellen. Das erstellte Objekt ist dasselbe, wie mit der ".Net-Klasse X509Certificate2" und "New-Object".

2.4 Zertifikatsverwaltung mit dem Quest QAD-SnapIn

Installation siehe: My Powershell -> Kapitel 3.3.3 Module und SnapIns

Alle QAD-cmdlets mit Beispielen: Powergui - QAD cmdlets reference


Beispiel 1: Auflisten von Zertifikaten mit QAD (Storelocation: LocalMachine, Store: My)

Get-QADLocalCertificateStore My LocalMachine | Get-QADCertificate | Format-Table -autosize
#Ausgabe

IssuedBy  IssuedTo              ValidFrom  ValidTo
--------  --------              ---------  -------
Dom1-CA01 DOM1CLI01.Dom1.intern 02.05.2011 05.05.2011
Dom1-CA01 DOM1CLI01.Dom1.intern 26.04.2011 29.04.2011
Dom1-CA01                       26.04.2011 25.04.2012
Dom1-CA01 DOM1CLI01.Dom1.intern 26.04.2011 25.04.2012
Dom1-CA01 DOM1CLI01.Dom1.intern 02.05.2011 01.05.2012
Dom1-CA01 DOM1CLI01.Dom1.intern 26.04.2011 25.04.2012
Dom1-CA01 DOM1CLI01.Dom1.intern 02.05.2011 30.05.2011
Dom1-CA01 DOM1CLI01.Dom1.intern 26.04.2011 24.05.2011
Dom1-CA01 DOM1CLI01.Dom1.intern 02.05.2011 01.05.2012

 

Beispiel 2: Anzeigen aller Zertifikate im LocalMachineStore

Das Skript kennezeichnet alle Zertifikate, bei denen das heutige Datum nicht im Gültigkeitszeitraum des Zertifikats liegt

function getcerts{
  param($store,$storelocation)
  $certs=Get-QADLocalCertificateStore $store $storelocation | Get-QADCertificate
  $certs | foreach {
     try{
        $ISOlderThanValidfrom=$(get-date)-$($_.validfrom)
        $ISOlderThanValidto=$(get-date)-$($_.validto)
        $a= "{0,-60}  {1:d}  {2:d}  {3:0}  {4:0}" -f $_.issuedto,$_.validfrom,$_.validto,$Store,$storelocation
        if ($ISOlderThanValidfrom -lt 0) {  
           write-host "$a  Dieses Zertifikatsbeginn ist noch nicht gültig" -backgroundcolor yellow 
        }elseif($ISOlderThanValidto -gt 0){
           write-host "$a  Dieses Zertifikat ist abgelaufen" -backgroundcolor yellow
        }else{
           write-host $a
        } #if
      }#try
      catch{
      } 
  } #foreach
} #Function

$storelocation="localmachine"
$stores=Get-QADLocalCertificateStore -StoreLocation $storelocation
$stores | foreach {
  getcerts $_.name $storelocation 
  }


Die Funktion getcerts liest alle Zertifikate des übergebenen Stores aus und prüft seine Gültigkeit bezüglich des Gültigkeitzeitraums. Einen anderen Ansatz mit .Net findet man in diesem sehr lesenswerten Artikel der Scripting Guys

Technet - ScriptingGuy: Use PowerShell and .NET to Find Expired Certificates

 

Beispiel 3a Anlage eines zusätzlichen Zertifikatsstores für den "aktuellen Benutzer" mit QAD

#erfordert die Installation und Registrierung des Quest-SnapIns

$storename = "TestUserStore04"
$storelocation = "Currentuser"
New-QADLocalCertificateStore -storename $storename -storelocation $storelocation

Im Vergleich zu Beispiel 1a, welches dasselbe Ergebnis liefert, ist dieser Weg sicherlich deutlich einfacher zu Skripten


Beispiel 3b: Löschen eines zusätzlichen Zertifikatsstores für den "aktuellen Benutzer" mit QAD

$storename = "TestUserStore03"
$storelocation = "Currentuser"

Remove-QADLocalCertificateStore -storename $storename -storelocation $storelocation

#identisch zu

Get-QADLocalCertificateStore -storename $storename -storelocation $storelocation | Remove-QADLocalCertificateStore

Einen vergleichbaren Code in native .Net habe ich nicht gefunden.

 

Beispiel 4: Exportieren aller Zertifikats aus dem Currentuser\my-Store in pfx-Dateien

$pw="hello"
Get-QADLocalCertificateStore My |  
 Get-QADCertificate | %{  
 Export-QADCertificate $_ -Mode chain -Format Pfx -Password (ConvertTo-SecureString $pw -asplaintext -force) -File c:\MyCerts\$($_.issuedto).pfx} | out-null

 Dieselbe Aufgabe lässt sich auch über reines .Net erledigen, wie in Beispiel 1b unter 2.2.3 Sonstige .Net Klassen gezeigt.

Die Verwendung des cmdlets "ConvertTo-SecureString" habe ich im Kapitel  Strings - 3. Verschlüsselung von Strings beschrieben

Weitere Beispiele für das cmdlet Export-QADCertificate: Export-QADCertificate

 

Beispiel 5: Ein Zertifikatsobjekt mit einem Quest-cmdlet erstellen

Das Beispiel zeigt den Unterschied bei der Verwendung der QAD-cmdlets und der .Net-Programmierung. Eine Kombination von Objekten, Methoden oder Eigenschaften zwischen beiden Techniken wird also nicht so ohne weiteres funktionieren. (siehe auch Erklärung am Ende des Skripts)

$Cert=@()
$cert=Get-QADLocalCertificateStore My LocalMachine | Get-QADCertificate  | select -first 1 | Format-Table -autosize
$cert
$cert.gettype() | Format-Table Name, BaseType -auto
$cert | gm
#Ausgabe

IssuedBy  IssuedTo              ValidFrom  ValidTo  
--------  --------              ---------  -------  
Dom1-CA01 DOM1CLI01.Dom1.intern 02.05.2011 05.05.2011


Name     BaseType   
----     --------   
Object[] System.Array


   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

Name                                    MemberType Definition                                                                             
----                                    ---------- ----------                                                                             
Equals                                  Method     bool Equals(System.Object obj)                                                         
GetHashCode                             Method     int GetHashCode() 
... 

Auch bei diesem Beispiel enthält die Variable $Cert ein Zertifikatsobject, allerdings keines der Klasse X509Certificate2, sondern der Klasse FormatStartData. Will man das Ergebnis weiterbearbeiten, muss man sich bei Quest und nicht in der MSDN informieren. (siehe: Quest ActiveRoles Management Shell for Active Directory).
 

3 Zertifikatstores vergleichen

Technet: Configure Trusted Roots and Disallowed Certificates
Technet: Event ID 8 — Automatic Root Certificates Update Configuration

3.1 Zertifikate in Ordnern

Beispiel 1: Zertifikate aus einem Fileordner auflisten

#certutil -syncwithwu c:\temp\certs
 
Clear-Host
Set-StrictMode -Version "2.0"
 
Function Main{
 
  $Certs = @()
  $Outlines = @()
 
  $Path = "H:\Powershell\certcompare\certs"
  $Certs = Get-Childitem -Path $Path
  
  $OutLines = $Certs.Fullname | showFileCertInfo 
  $OutLines
}
 
function readFile{
# Einlesen eines Zertifikatfiles in ein Bytearray
    param($filename)
    $FileStream = New-Object System.IO.FileStream ($filename,[System.IO.FileMode]::Open,[System.IO.FileAccess]::read)
    [int]$size = [math]::truncate($filestream.Length)
    [byte[]] $data = new-object byte[] $size
    $filestream.Read($data, 0, $size) | out-null
    return $data
}
 
function showFileCertInfo{
      
    Begin{
      $Certs = @()
    }#Begin 
 
    Process{
      $X509 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2   
      [byte[]] $rawdata = readfile -filename $_
      #'Create X509Certificate2 object from .crt file.
      $X509.import($rawdata)
      $Certs += "$($x509.Thumbprint)   $($X509.NotAfter)"
    }#Process
     
     End{
        Return ,$Certs
     }#End
       
 }#function  showCertInfo  
 
Main
#mögliche Ausgabe

027268293E5F5D17AAA4B3C3E6361E1F92575EAA   08/24/2025 10:05:46
02FAF3E291435468607857694DF5E45B68851868   05/30/2020 12:48:38
039EEDB80BE7A03C6953893B20D2D9323A4C2AFD   12/02/2037 00:59:59
 

Beispiel 2: Schnittmengen von Zertifkaten in verschiedenen Verzeichnissen
#certutil -syncwithwu c:\temp\certs
 
Clear-Host
Set-StrictMode -Version "2.0"
 
Function Main{
 
  #Set Outfile 
  Try{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    $ThisScriptPath = Split-Path $Invocation.MyCommand.Path
    }Catch{
     Write-Host "Skript vor dem ersten Einsatz bitte abspeichern!" -BackGroundColor Red
     Break
   }
  $TimeStamp = (Get-Date).ToString("yyyyMMdd_hhmmss")
  $CSVOutfilePath_Base = "$ThisScriptPath\certs-$TimeStamp.csv"
  ""
 
  $Path01 = "H:\Powershell\certcompare\certs01"
  $Path02 = "H:\Powershell\certcompare\certs02"
 
  $Certs01 = Get-Childitem -Path $Path01
  $Certs02 = Get-Childitem -Path $Path02
 
 
  $CertFiles = @()
  $Outlines = @()
  
  Write-Host ""`n"CertFiles, die in GroupA, aber nicht in GroupB sind -NotAnd-" -BackgroundColor DarkRed -ForegroundColor DarkYellow
  $CertFiles = $Certs01 | Where {$Certs02.Name -NotContains $_.Name } #Names
  $OutLines = @($CertFiles.Fullname | showCertInfo) 
  $OutLines
  ""
  Write-Host ""`n"Member, die sowohl in GroupA, als auch in GroupB sind -And-" -BackgroundColor DarkRed -ForegroundColor DarkYellow
  $CertFiles = $Certs01 | Where {$Certs02.Name -Contains $_.Name } #Names
  $OutLines = @($CertFiles.Fullname | showCertInfo)
  $OutLines
  ""  
  Write-Host ""`n"Alle Members in GroupA oder GroupB. Duplikate entfernen -Or-" -BackgroundColor DarkRed -ForegroundColor DarkYellow
  $CertFiles = $Certs01 + $Certs02 | sort -Unique
  $OutLines = $CertFiles.Fullname | showCertInfo
  $OutLines
}
 
 
function readFile{
# Einlesen eines Zertifikatfiles in ein Bytearray
    param($filename)
    $FileStream = New-Object System.IO.FileStream ($filename,[System.IO.FileMode]::Open,[System.IO.FileAccess]::read)
    [int]$size = [math]::truncate($filestream.Length)
    [byte[]] $data = new-object byte[] $size
    $filestream.Read($data, 0, $size) | out-null
    return $data
}
 
function showCertInfo{
      
    Begin{
      $Certs = @()
    }#Begin 
 
    Process{
      $X509 = new-object System.Security.Cryptography.X509Certificates.X509Certificate2   
      [byte[]] $rawdata = readfile -filename $_
      #'Create X509Certificate2 object from .crt file.
      $X509.import($rawdata)
      $Certs += "$($x509.Thumbprint)   $($X509.NotAfter)"
    }#Process
     
     End{
        Return ,$Certs
     }#End
       
 }#function  showCertInfo  
 
 Main
#mögliche Ausgabe

CertFiles, die in GroupA, aber nicht in GroupB sind -NotAnd-
00EA522C8A9C06AA3ECCE0B4FA6CDC21D92E8099    09/15/2020 16:59:59
 
Member, die sowohl in GroupA, als auch in GroupB sind -And-
0B77BEBBCB7AA24705DECC0FBD6A02FC7ABD9B52    08/02/2028 01:59:59
0B972C9EA6E7CC58D93B20BF71EC412E7209FABF    12/31/2037 01:00:00
 
Alle Members in GroupA oder GroupB. Duplikate entfernen -Or-
00EA522C8A9C06AA3ECCE0B4FA6CDC21D92E8099    09/15/2020 16:59:59
0B77BEBBCB7AA24705DECC0FBD6A02FC7ABD9B52    08/02/2028 01:59:59
0B972C9EA6E7CC58D93B20BF71EC412E7209FABF    12/31/2037 01:00:00
1B8EEA5796291AC939EAB80A811A7373C0937967    01/12/2042 18:27:44


3.2 Zertifikate aus bestimmten Stores auslesen

Beispiel 1: Auflisten aller Stores
[System.Enum]::GetNames([System.Security.Cryptography.x509Certificates.Storename])
#mögliche Ausgabe

AddressBook
AuthRoot
CertificateAuthority
Disallowed
My
Root
TrustedPeople
TrustedPublisher


Beispiel 2: Auslesen der Zertifikate aus dem Computer Root- und AuthRootStore
Clear-Host
Set-StrictMode -Version "2.0"

Function Main{
  Read-Store "Root" #Trusted Root Certification Authorities"
  Read-Store "AuthRoot" #Third-Party Root Certification Authorities
}

Function Read-Store{
  Param($Store)
  $Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("$Store","LocalMachine")
  $Store.Open("ReadOnly")
  $X509s = @($Store.Certificates)
  #$Certs.count

  $StoreCerts = @()
  Foreach ($X509 in $X509s){
      $Cert = New-Object -TypeName Psobject -Property @{
      "Subjectname" = $($X509.Subjectname);
      "FriendlyName" = $X509.FriendlyName;
      "Subject" = $X509.subject;
      "Issuer" = $X509.Issuer;
      "Thumbprint" = $X509.Thumbprint;
      "NotAfter" = $X509.NotAfter;
      "NotBefore" = $X509.NotBefore;
       }#Psobject
   $StoreCerts += $Cert
  } #foreach
 
   "Store: {0} - Count: {1} `n" -f $($Store.name),$($StoreCerts.count)
   $StoreCerts | sort NotAfter| ft Thumbprint,Friendlyname,NotAfter
   "-" * 60
} #End ReadStore

Main
#mögliche Ausgabe (gekürzt)

Store: Root - Count: 29


Thumbprint                               FriendlyName                            NotAfter                               
----------                               ------------                            --------                               
245C97DF7514E7CF2DF8BE72AE957B9E04741E85 Microsoft Timestamp Root                31.12.1999 00:59:59                    
7F88CD7223F3C813818C994614A89C99FA3B5247 Microsoft Authenticode(tm) Root         01.01.2000 00:59:59                    
4F65566336DB6598581D584A596C87934D5F2AB4 VeriSign                                08.01.2004 00:59:59                    
...

------------------------------------------------------------
Store: AuthRoot - Count: 21


Thumbprint                               FriendlyName                            NotAfter                               
----------                               ------------                            --------                               
4F65566336DB6598581D584A596C87934D5F2AB4 VeriSign                                08.01.2004 00:59:59                    
97E2E99636A547554F838FBA38B82E74F89A830A VeriSign                                19.05.2018 01:59:59                    
97817950D81C9670CC34D809CF794431367EF474 GTE CyberTrust Global Root              14.08.2018 01:59:00                    
...


------------------------------------------------------------

 

4 Microsoft Trusted Root Certificate Program

Zunächst ein paar allgemeine Anmerkungen:

  • Wie im nächsten Unterkapitel 3.1 gezeigt wird, kann man per Policysetting das "Trusted Root Certificate Program" ein- und ausschalten
  • Mit der Nutzung "Microsoft Trusted Root Certificate Programm" wird die Verwaltung vertrauenswürdiger und nicht vertrauenswürdiger Stammzertifikate recht einfach.
  • Die securitytechnisch doch sehr wichtige Einschätzung der vertrauenswürdigen Stammzertifikate und der nicht vertrauenswürdigen Stammzertifikate wird Microsoft überlässen.
  • Mehr Kontrolle über die Source des  "Trusted Root Store" und der "Disallowed Certificates" kann mit Umsetzung dieses Artikels Configure Trusted Roots and Disallowed Certificates erreicht werden. Dadurch kann man konfigurieren, dass sich die von der GPO betroffenen Rechner nicht mehr die root- und disallowed certificates online vom Microsoft Update Server, sondern von einem selbst administrierten File- oder Webserver downloaden.
  • Die von Microsoft bezogenen Zertifikatscontainer (*.sst) bzw. Zertifikatslisten (*.ctl)  unterliegen einem gewissen Lizenzschutz, dürfen also nicht so einfach verändert werden. Bei Bedarf setzt euch am besten mit dem Microsoft Support oder einem Lizenz-Profi in Verbindung.
  • Bei weitem nicht jede Software orientiert sich an den Microsoft Zertifikaten. Mozilla Firefox oder Google Chrome etwa bringen ihr eigenen Trusted Root Zertifikate mit.
  • Bei aktivertem Root Update fragen Clients alle 24h beim Update Server nach dringenden Änderungen nach

 

4.1 Automatic Root Certificate Update 

Etwas versteckt finden sich die PolicySettings zum De- bzw. Aktivieren und Konfigurieren des automatische Root-Updates

 

4.1.1 Funktionsweise des Update Root Programs

Jeder Standalone Windows Client hat von Haus aus das "Update Root Program" aktiviert. Man muss sich bewusst sein, dass man es damit Microsoft überlässt zu bestimmen, welche Rootzertifkate vertrauenswürdig sind und welche nicht. Mit einem Rootzertifkat samt privaten Schlüssel hat ein Angreifer eine Menge Möglichkeiten in einer Umgebung beträchtlichen Schaden anzurichten

- Software, Treiber und Skripte gültig zu signieren

- Smartcards für jeden Domain-User auszustellen und damit etliche PKI-Schutzmechanismen auszuhebeln

- https-Websites im Intranet zu faken  

- etliche mehr.
 

Wie funktioniert also das "Update Root Program"?
Wird einem Client ein Zertifkat zur Prüfung vorgelegt, so durchsucht dieser Client nach einigen anderen Checks im lokalen Store "Trusted Root Certification Authorities", ob dort das zur Prüfung notwendige Root-Zertifikat vorhanden ist. Ist dies nicht der Fall, frägt der Client beim Windows Update Server zuerst nach der CTL (Certificate Trust List) authroot.stl. In der authroot.stl befindet sich die Liste der von Microsoft als vertrauenswürdig eingestuften Rootcertificate.

Befindet sich das benötigte Zertifkat in der CTL, so lädt der Client anschließend das Zertifikat in "Trusted Root Certification Authorities" und die Zertifikatskette ist vollständig.

 

Gewissensfrage: Kann man Microsoft bei der Auswähl der vertrauenswürdigen Rootzertifkate vertrauen?
Wie kommt man auf die Liste?
Microsoft setzt hierfür strenge Maßstäbe: Microsoft Trusted Root Certificate: Program Requirements  

Wer ist alles auf der Liste der vertrauenswürdigen Rootzertifikate?

Windows and Windows Phone 8 SSL Root Certificate Program (Member CAs)

öffnet man die momentan aktuelle PDF-Datei von 2014, so sieht man eine nicht so kleine Liste von 350 als vertrauenswürdig eingestuften Root Zertifikaten aus aller Herren Länder. Hier nur ein kleiner Auszug:

Schafft ein Angreifer es sich den privaten Schlüssel von einen dieser Zertifikate zu besorgen, so hat er mehr oder weniger gewonnen. Mit dem notwendigen Kleingeld und entsprechenden Beziehungen sollte es nicht bei allen 350 RootCAs gänzlich unmöglich sein, sich einen privaten Schlüssel zu besorgen. (unbewiesene persönliche Einschätzung!)

Kommt es häufiger vor, dass Rootzertifikate kompromittiert werden?

Inadvertently Disclosed Digital Certificates Could Allow Spoofing (DLink - September 2015)

Inadvertently Disclosed Digital Certificates Could Allow Spoofing (Dell - November 2015)
Die beiden Beispiele sind nicht in der Microsoft Liste vertrauenswürdiger Zertifkate enthalten!, zeigen aber dennoch, dass auch bekannte Firmen wie Dell oder Dlink es nicht zuverlässig schaffen, ihre Rootzertificate sicher zu schützen. Googelt einfach mal nach "Inadvertently Disclosed Digital Certificate Allow Spoofing" für weitere Beispiele

 

4.1.2 Alternativen zum Update Root Program

a) GPO

Der Rootstore lässt sich über eine GPO auch bequem auch manuell administrieren. Die Root- und Untrusted Zertifikate können mit certutil auf Commandline lokal herunter geladen werden und nach Prüfung lokal in der Domäne verteilt und wieder zurückgezogen werden.

certutil -syncwithwu c:\temp\CTL
Anhand der Thumbprints und der PDF-Datei von 3.1.1 kann man die Zertifikate auswählen, denen man vertrauen möchte. Es kann dann natürlich vorkommen, dass ein Domain User in Brasilien nicht mehr auf das Homebanking seiner dortigenBank zugreifen kann, bevor ein Administrator das notwendige Rootzertifkat in die Policy importiert hat.
Schwierig ist es eher einen Prozess zu definieren, wer in der eigenen Firma Root Certificate prüft und freigibt.

b) LDAP-Store

Zertifikate für den Trusted Root Store können auch direkt im LDAP mit
certutil f dspublish “xyzRoot Certificate.crt RootCA
gespeichert werden.
Der Vorteil liegt hier, dass die Rootzertifikate im gesamten LDAP-Forest über alle Domänen und Unterdomänen verteilt werden. 
Der Nachteil dieser Methode, ist der -zumindest mir- nicht transparente Verteilmechanismus an die Domänenrechte. Es kann recht lange dauern, bis die Clients sich aus dem LDAP-Store die Rootzertifikate herausziehen. 

Das Entfernen von Root-Zertifikaten geschieht glaube ich am Einfachsten mit adsiedit.msc

 

4.1.3 Zertifkatscontainer der unterschiedlichen Quellen am Client

Die verschiedenen "Physical certificate stores" sind nicht default sichtbar.


Die Stores sind additiv. Es können also Rootzertifkate über unterschiedliche Wege zu einem Client gelangen.

 

4.2 Untrusted Certificates 

Ein wichtiger ZertifikatsContainer auf jedem Rechner ist der "Untrusted Certificates" bzw. "Nicht vertrauenswürdige Zertifikate", der sich mit den oben genannten .Net Klassen und der Powershell auch gut verwalten lässt.
 
Dieser Container enthält also Zertifikate, denen man nach Microsoft's Meinung nicht mehr trauen sollte. Neben der CRL (Certificate Revocation List) ist dies eine weitere Möglichkeit Zertifikate zu sperren, die insbesondere für Rechner ohne Zugriff auf aktuelle CRLs interessant ist. Zu beachten ist aber, dass von den Browsern sich natürlich nur der Internet Explorer (Edge) um diese Liste kümmert.
Firefox oder Chrome haben ihre eigenen Mechanismen.
Mozilla aktualisiert den Zertifikatsstore des Firefox mit jedem Update

siehe: Mozilla CA Certificate Store
 

Download der Microsoft Untrusted Certificates (sst-Container)

Möchte oder kann man den "Untrusted Certificates" Store nicht automatisch per Update Root Programm oder per Hotfix aktualisieren, kann man sich die Zertifikate auch in einem SST-Container downloaden. 

siehe: Microsoft Security Advisory 3097966
 

Auf einem mit dem Internet verbundenen Rechner kann man mit dem Befehl

certutil -syncwithwu c:\temp\certs

alle Zertifikate für den "Trusted Root Store" und den sst-Container mit den Untrusted Certificates als Files von Microsoft laden.
Den sst-Container alleine kann man über

http://ctldl.windowsupdate.com/msdownload/update/v3/static/trustedr/en/disallowedcert.sst
downloaden (ohne Garantie, dass der Link immer und ewig gültig ist: ich habe einfach einen Netzwerkmonitor während des certutil-Kommandos laufen lassen)

 

der SST-Container lässt sich einfach per Doppelklick in der MMC öffnen und betrachten