Get-TCPCert

Am 1.1. 2017 werden viele Browser eine Warnung ausgeben, wenn das per SSL angesprochene Zertifikat noch mit dem hashverfahren SHA1 signiert ist. Das Verfahren ist nicht mehr als sicher anzusehen. Nur wie finden Sie in ihrem LAN oder der DMZ heraus, welches Zertifikat wo gebunden ist und welche Eigenschaften es hat?. Das Skript Get-TCPCert hilft dabei, dies zu ermitteln, indem es eine Liste der Hosts (Namen oder IP-Adressen) und optional von Ports bekommt und per TCP eine Verbindung aufbau, das Zertifikat lädt und das Ergebnis ausgibt.

Das Skript ist in PowerShell geschrieben, so dass Sie es zum einen anpassen können aber insbesondere um über die Pipeline es mit Daten zu füttern und die Ausgaben weiter zu verarbeiten. Zudem können Sie sich vielleicht die ein oder andere Umsetzung dabei auch für eigene Skripte abschauen. Ich habe anders als sonst üblich eine Debugausgabe mit "Write-Host" (Siehe auch Write-Host Debugging) realisiert, da das Skript für eine interaktiven Start ausgelegt ist und daher ich nicht den Einsatz von Start-Transcript vorgesehen habe.

Einsatz

Das Skript erwartet als Eingabe den oder die Computernamen oder IP-Adressen und optional mit einem Doppelpunkt abgetrennt den Port. Alternativ können Sie nur die Computer einspeisen und die Ports als Parameter angeben. Die Ausgabe ist dann wieder ein PSObject, welches sie einfach als Tabelle oder Liste ausgeben, mit "where" filtern oder mit export-csv in einer Datei ausgeben lassen können. Sie können das Skript also auf unterschiedlichste Weise mit Daten füllen. Ein Blick in den Sourcecode zeigt die möglichen Parameter:

[cmdletbinding()]
param (
    [parameter(ValueFromPipeline=$True)]
    [string]$remotehost = "localhost",
    $portrange=443,
    $tcptimeout= 1000   # wait up to 1Sec for TCP Connection
)

Der Inhalt von "remotehost" kann also per Pipeline oder manuell übergeben werden. die Portrange ist mit 443 vorbelegt aber kann als Parameter ebenfalls angepasst werden. Hier kann auch ein Array mit mehreren Ports angegeben werden. Den TCP-TimeOut habe ich auf 1 Sekunde reduziert. Das "sollte" speziell im LAN immer reichen und beschleunigt doch das Abscannen vieler Systemen. Bei Bedarf kann der Wert natürlich angepasst werden.

Aufruf

Hier ein paar Beispiele

# einfacher Aufruf mit einem Hostname und Port
PS C:\Get-TCPCert> .\Get-TCPCert.1.1.ps1 -remotehost www.msxfaq.de -portrange 443
Get-LANCert: Start
------------- Get-LANCert:Processing www.msxfaq.de
 Using PortRange
 Iteration PortRange 443
 Init Result
 Connect to www.msxfaq.de:443 Connected
 Get TCP-Stream
 Get SSL-Stream
 AuthenticateAsClient HandshakeOK
 Read the certificatedone
  Parsing Certificate Data
    CN= CN=www.msxfaq.de
  Closing Connection
  Sending Result to Pipeline


Computername                   : www.msxfaq.de
Port                           : 443
Status                         : OK
CN                             : CN=www.msxfaq.de
Subject                        : CN=www.msxfaq.de
NotAfter                       : 16.08.2017 01:59:59
NotBefore                      : 15.08.2016 02:00:00
Issuer                         : CN=Secure Site Starter DV SSL CA - G2,
                                 OU=Domain Validated SSL, O="GeoTrust, Inc.",
                                 C=US
Thumbprint                     : 0C3E7A947B931618D0F2F087107F5B4E8BAC62B4
SerialNumber                   : 182CBFE914C03D9B5BB50F0EC51FBD44
SignatureAlgorithmFriendlyName : sha256RSA

  Done
Get-LANCert:End
# Scan eines Subnetz auf WebServer

(1..254) | %{"10.1.1.$_"} | .\Get-LANCert.ps1 -portrange 443

Das sind nur ein paar Beispiele. Sie können natürlich auch z.B. mit "Get-ADComputer" alle Computer in ihrem Active Directory abfragen. Interessanter fände ich dann aber eine Abfrage aller im DNS hinterlegten A und CNAME-Einträge, Sie so auch Systeme ohne Computerkonto, z.B.: virtuelle Rechnernamen finden. das geht seit Windows 2012 auch per Powershell

Get-DnsServerResourceRecord -ZoneName example.com | Where-Object {$_.RecordType -eq "A" -or $_.RecordType -eq "CNAME"}

Für ältere Versionen wäre dann eine WMI-Abfrage der Weg die Daten zu erhalten.

Get-WmiObject `
   -Class Microsoftdns_atype `
   -Namespace "root\microsoftdns" `
| where {$_.ownername.endwith(".msxfaq.de"} `
| foreach {$_.ownername}

dc1.msxfaq.de
sfb.msxfaq.de

Diese Liste kann man so natürlich auch an das Skript übergeben, wenn Sie Zugriff auf den DNS-Server per WMI haben.

Ausgabe

Die Ergebnisse von Get-TCPCert landen über die Pipeline per Default auf dem Bildschirm. sie können diese über ein "PIPE"-Symbol natürlich an andere Prozesse weitergeben oder über eine Variablenzuweisung zwischenspeichern. Wer sich mit PowerShell auskennt, sollte keine Probleme damit haben, die folgenden Beispiele zu verstehen:

# Einsammeln der Zertifikate von cas1.excample.com bis cas9.example.com
$ergebnis= ( (1..9) | %{"cas$_.example.com"} | .\Get-TCPCert.ps1 -portrange 443

# gefilterte Ausgabe auf alle mit SHA1
$ergebnis | where {$_.status -eq "WarnSHA1"}

# gruppierte Ausgabe nach dem Status
$ergebnis | group status
 
Count Name                      Group
----- ----                      -----
    2 NoConnection              {@{Computername=cas1.example.com; Port=443; S
    3 WarnSHA1                  {@{Computername=cas4.example.com; Port=443; S
    4 OK                        {@{Computername=cas2.example.com; Port=443;
    1 AuthFail                  {@{Computername=cas9.example.com; Port=443;

#Export der Ausgaben in eine CSV-Datei

(1..254) | %{"10.1.1.$_"} | .\Get-LANCert.ps1 -portrange 443 | export-csv .\certresult.csv

Genau genommen können Sie die Ausgabe auch noch filtern und mit einem eigenen Skript zum Computerkonto den Administrator ermitteln und per Mail informieren. Die CSV-Datei können sie aber genauso einfach in Excel öffnen.

Download

Das PowerShell-Script ist keine "fertige Lösung", sondern sie müssen über die Parameter und Ausgabeauswertung die gewünschten Ergebnisse erzeugen lassen. Ich hoffe ich habe die meisten Fehler und Sonderfälle abgefangen aber es kann durchaus passieren, dass die Auswertung unvollständig ist. Es ist eine früher Version aber in Anbetracht der Deadline 1.1.2017 (Siehe SHA-256 und Keylänge) wollte ich das Skript nicht länger zurück halten.

get-tcpcert.1.1.ps1.txt

Das Skript kann durchaus noch "verbessert" werden.

Es gibt allerdings eine Einschränkung: Das Skript kann nur Zertifikate prüfen, die bei Verbindungen über TCP auch genutzt werden. Es kann z.B. keine "internen" Zertifikate prüfen, die z.B. bei Smartcards, EFS oder auch ADFS eingesetzt werden. Ein "vollständiges" Inventory ihrer jemals ausgestellten Zertifikate können Sie bei ihrer internen PKI auslesen. Und die externen "öffentlichen" Zertifikate können Sie im Portal der öffentlichen PKI einsehen oder auf der Rechnung in der Buchhaltung nachschauen.

Weitere Links