Aktualisieren der Windows Certificate Trust Lists in „disconnected environments“

Die Certificate Trust Lists sind die von Microsoft im Regelfall automatisch mit Windows Update aktualisierten Listen, ob einer Certificate Authority vertraut wird oder ob bestimmte Zertifikate zurückgezogen wurden und daher nicht mehr vertrauenswürdig sind.

Insgesamt ein sensiblen Thema, da es bereits genug Vorfälle gab, wo bis dahin gültige Zertifikate zur Treibersignierung entwendet wurden und Malware signiert wurde. Vor so einem „falschen Treiber“ schützt einen nur eine aktuelle Liste von gültigen Zertifikaten.

Bei so gut wie allen Unternehmen werden die Windows Server über ein dediziertes Patchmanagement mit den Aktualisierungen aus Redmond versorgt und nicht per Windows Update. Sei es mit dem Microsoft System Center Configuration Manager oder Symantecs Patch Management Solution – eines ist meistens identisch: Die Certificate Trust Lists werden nicht mit aktualisiert.

Microsoft hat sich merkwürdigerweise dazu entschieden, diese Listen nur direkt per Windows Update zu aktualisieren. Für sogenannte „disconnected environments“ hat Microsoft im Jahr 2013 ein Security-Update herausgebracht, dass ein paar Workarounds liefert, damit diese Listen von den Systemen z.B. von einer Netzwerk-Freigabe bezogen werden können.

Die Listen müssen regelmäßig in die Netzwerk-Freigabe geladen werden, damit die per GPO konfigurierten Systeme diese beziehen und mit aktuellen Listen versorgt sind. Zugriff benötigen neben einem Benutzer, der diese Freigabe per Scheduled Task regelmäßig füllt (Read/Write) auch die Domain Computers (Read).

Wer möchte, der kann sich auch eine ADM-Datei (RootDirURL.adm) bauen und die auf den Systemen notwendigen Einstellungen per Gruppenrichtlinie verteilen. Die notwendigen Einstellungen sind im bereits oben genannten KB-Artikel zu finden.

Da einen Microsoft jedoch damit alleine lässt, wie man diese Listen regelmäßig heruntergeladen bekommt, habe ich dafür ein paar PowerShell-Zeilen zusammengeschrieben. Voraussetzung ist, dass der ausführende Server entweder einen Zugang zum Internet hat oder diesen per vom Script einzutragenen Proxy temporär erhalten kann.

Sollte das Script bei der Ausführung auf einen Fehler stoßen, wird dies im EventLog des Systems im Application Log unter der EventID 41020 notiert. Sollte alles glatt verlaufen sein, wird auch dies unter EventID 41020 eingetragen, jedoch nicht als Error, sondern als Information. So kann man den Vorgang auch mit dem eigenen Monitoring-Tool überwachen.

Das Script findet Ihr auch im GitHub-Repository.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<#
.SYNOPSIS
Downloads the Trusted Root Authority Certificates, Untrusted Certificates List, Revocation Lists and Root List Signer Lists.
 
.DESCRIPTION
The Trusted Root Authority Certificates, Untrusted Certificates List, Revocation Lists and Root List Signer Lists are by default downloaded and updated by windows update.
This script downloads the neccessary files from windows update and saves them on a central destination, so the files can be imported by group policy settings.
 
.PARAMETER proxy
If defined as true, the script sets an proxy server and deletes these settings after.
 
.PARAMETER share
This parameter is mandatory and is used to place the downloaded files within the network.
 
.NOTES 
    File Name	: Update-WindowsCertificateStore.ps1
    Author		: Timo Ewiak (tew@logikkreise.de)
 
.EXAMPLE
.\Update-WindowsCertificateStore.ps1
.\Update-WindowsCertificateStore.ps1 -proxy proxy:80 -share \\DEV.LAN\system$\RootCertificates
#>
 
Param (
	[Parameter(Mandatory=$true)]
    $share,
    [Parameter(Mandatory=$false)]
    $proxy
)
 
############## DEFINING VARIABLES START #############################
$certutil = "C:\Windows\System32\certutil.exe"
$Arguments = "-syncWithWU $share"
$netsh = "C:\Windows\System32\netsh.exe"
$ProxySet = "winhttp set proxy proxy-server=$proxy"
$ProxyRemove = "winhttp reset proxy"
############## DEFINING VARIABLES END #############################
 
if (![System.Diagnostics.EventLog]::SourceExists("Update-WindowsCertificateStore"))
{
    New-EventLog -LogName "Application" -Source "Update-WindowsCertificateStore"
}
 
# Delete the old files within the share
Remove-Item "$share\*" -Recurse -Force -ErrorAction Stop
 
# Set the proxy if the variable is defined
if($proxy -ne $null){
 
    Start-Process -FilePath $netsh -ArgumentList $ProxySet -Wait -NoNewWindow -ErrorAction Stop
}
 
# Tests if it can reach the download servers from microsoft.
# Starts the download of the neccessary files and saves them to the defined network share.
if(Test-NetConnection ctldl.windowsupdate.com){
 
    $log = Start-Process -FilePath $certutil -ArgumentList $Arguments -Wait -NoNewWindow -ErrorAction Stop -PassThru
    #$log.ExitCode | Out-File -FilePath "$PSScriptRoot\error.txt"
    $errorcode = $log.ExitCode
 
	# Write Event-Log-Entry if success
    if($log.ExitCode -eq "0")
    {
        Write-EventLog -LogName Application -source Update-WindowsCertificateStore -eventID 41020 -EntryType Information -message "Successfully downloaded the Trusted Root Authority Certificates, Untrusted Certificates List, Revocation Lists and Root List Signer Lists." -ErrorAction Stop
    }
 
	# Write Event-Log-Entry if error
    if($log.ExitCode -ne "0")
    {
        Write-EventLog -LogName Application -source Update-WindowsCertificateStore -eventID 41020 -EntryType Error -message "Something went wrong. Could not download the files from microsoft, cause error code: $errorcode" -ErrorAction Stop
    }
}
 
# Delete the proxy after usage and if the variable is defined
if($proxy -ne $null){
 
    Start-Process -FilePath $netsh -ArgumentList $ProxyRemove -Wait -NoNewWindow -ErrorAction Stop
}

Windows Printserver – Berechtigungen auf vorhandenen Druckern hinzufügen

Vor kurzem stand ich vor der Herausforderung, dass ich auf mehreren Printservern neue Berechtigungsgruppen eintragen musste, um bestimmten Personengruppen erweiterte Berechtigungen auf den dort installierten Druckern zu erteilen. Da es sich dabei um mehr als 500 Drucker handelte, wollte ich logischerweise ungerne jedes einzelne Gerät händisch anfassen.

Die Berechtigungen, die man nachträglich auf Ebene des Printservers vergibt, werden leider nur bei neuen Einrichtungen übernommen, nicht aber bei vorhandenen vererbt.

Ich habe dafür also ein kleines PowerShell-Script geschrieben und stelle es einfach mal zur Verfügung, sollte jemand vor der gleichen Aufgabe stehen und ich Ihm damit ein wenig helfen können.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<#
.SYNOPSIS
A tiny script to add a user or group to the access control list of a printer installed on a print server.
 
.DESCRIPTION
The permissions on print server level are not inherited to the printers. Only new installed printers will copy the permissions.
Present printers will not get these new permissions or permission changes. This little script will add the group or user to all installed (and shared) printers. You need the subinacl Tool from Microsoft to run this script: https://www.microsoft.com/en-us/download/details.aspx?id=23510
 
.PARAMETER Group
Defines the user or group that will be added to the acl.
 
.PARAMETER Permissions
Defines the permission that the group will get. You can commit more than one permission.
Printer:
    F = Full Control
    M = Manage Documents
    P = Print
 
.PARAMETER Server
Defines the print server. Please use the full qualified domain name here.
 
.NOTES 
    File Name	: Set-PrinterPermissions.ps1
    Author		: Timo Ewiak (tew@logikkreise.de)
 
.EXAMPLE
.\Set-PrinterPermissions.ps1 -group "PRT_Manage-Printer-Objects_EDIT" -Permission "MP" -Server "SERVER1.DEV.LAN"
.\Set-PrinterPermissions.ps1 -group "PRT_Manage-Printer-Objects_FULL" -Permission "F" -List ".\Desktop\Printers.txt"
#>
 
Param (
	[Parameter(Mandatory=$true)]
    $Group,
    [Parameter(Mandatory=$true)]
    $Permission,
    [Parameter(Mandatory=$false)]
    $Server,
	[Parameter(Mandatory=$false)]
    $List
)
 
############## DEFINING VARIABLES START #############################
$subinacl = "$PSScriptRoot\subinacl.exe"
$LogPath = "$PSScriptRoot\Set-PrinterPermissions.log"
############## DEFINING VARIABLES END #############################
 
if($List)
{
	$Server = Get-Content -Path $List -Encoding UTF8 -ErrorAction Stop
}
 
try {    
    if($List -or $Server)
    {
        ForEach($Server in $Servers)
        {
            $Printers = Get-Printer -Computername $Server | Where-Object {$_.Published -eq $false} -ErrorAction Stop
            ForEach($Printer in $Printers)
            {
                $PrinterSharePath = "\\" + ($server).split(".")[0] + "\" + $Printer.sharename
 
                Write-Host $PrinterSharePath | Out-File -FilePath $LogPath -Encoding utf8 -Append -ErrorAction Stop
                $Arguments = "/printer $PrinterSharePath /Grant=$Group=$Permission"
                Start-Process -FilePath $subinacl -ArgumentList $Arguments -Wait -ErrorAction Stop
            }
        }
    }
}    
catch {
    if(!$List -or !$Server)
    {
        Write-Host "Please define a single server or a simple list. Both variables are empty."
    }
}

The certificate template could not be loaded. Element not found. 0x80070490

Vor wenigen Tagen stieß ich nach der Einrichtung eines neuen Certificate Templates auf einer Microsoft Enterprise CA auf folgende Fehlermeldungen innerhalb des Application Event Logs.

Der Server der SubCA gibt an, dass er das neue Template nicht finden könne. Per ADSI war dieses Template jedoch erfolgreich innerhalb der Domäne repliziert worden. Eine versuchte Ausstellung eines Zertifikats mit jenem Template scheiterte jedoch. Auch der Network Device Enrollment Server meldete, dass entsprechende Template würde von der CA nicht unterstützt.

Die Ursache für die Störung war am Ende, dass ich die Benutzergruppe „Authenticated Users“ auf dem Security-Reiter des Templates entfernt habe und einzig die „Enterprise Admins“, „Domain Admins“ und eine granulare Benutzergruppe für das Template hinzugefügt hatte.

Microsoft verlangt ausdrücklich die Gruppe „Authenticated Users“ (deutsch: Authentifizierte Benutzer) innerhalb der Berechtigungen für ein Certificate Template, wie sie selbst auch im TechNet unter KB283218 erklären.

Umzug des Blogs auf neuen Server

Ich bin die Tage mit dem Blog von Ubuntu 12.04 LTS mit Apache, PHP5 und MySQL auf ein Ubuntu 16.04 LTS mit Nginx, PHP7 und MariaDB umgezogen. Nach aktuellem Stand sollte alles wieder erreichbar und korrekt verlinkt sein, auch ein frisches Letsencrypt-Zertifikat ist wieder mit am Start.

TLS 1.0 in Windows Server 2008 R2 deaktivieren bricht Remote Desktop Services

Nach den vielen Sicherheitslücken in und rund um SSL und TLS geht es ja sinnvollerweise langsam in Richtung der Deaktivierung älterer Verschlüsselungsprotokollen wie TLS1.0. Von diesen Änderungen sind natürlich auch Bestandssysteme nicht ausgenommen, die nur selten auf der aktuellsten Betriebssystemversion betrieben werden.

Bei Microsoft Windows Server 2008 R2 kommen nach der Deaktivierung von TSL1.0 hingegen ein paar weitreichendere Einschränkungen hinzu. So unterstützen die Remote Desktop Services von Haus aus leider nicht Verbindungen mit TLS1.1 oder TLS1.2.

Dieses Feature wird erst mit einem von Microsoft unter KB3080079 bereitgestellten Update nachgereicht. Nach der Installation ist ein Neustart des Systems notwendig.

Printbrm.exe – The following error occurred: 0x80004005. Unspecified error.

Da Microsoft leider nicht die Möglichkeit eines Print-Clusters vorsieht, müssen andere Möglichkeiten ergriffen werden, sofern es zu einem Ausfall eines Printservers kommt. Eine Möglichkeit wäre die Einspielung eines aktuellen per PrintBRM erstellten Backups auf einem Reserve-Server.

Ein regelmäßig laufendes Scheduled Task kann das Backup zum Beispiel an zentraler Stelle ablegen. Etwas unglücklich ist, wenn das Tool mir dem leider nicht sehr aussagekräftigen Fehler 0x80004005 abbricht und kein Backup erstellt wird.

Normalerweise wird das Backup von PrintBRM im CAB-Format abgespeichert. Dieses Format wurde laut Microsoft nie für Dateien über 2 GByte konzipiert. Sofern ein PrintBRM-Backup diese Größte erreicht, wird das Tool mit dem genannten Fehler abbrechen.

Dieser Fehler ist beschränkt auf Microsoft Windows Server 2008 bis 2008 R2. Mit Microsoft Windows Server 2012 wurde das Tool um die Funkion erweitert, dass Backups im OPC-Format gespeichert werden und diese auch bei mehr als 2 GByte nicht schlapp machen.

Damit ist das Problem jedoch für Print Server auf Basis von Windows Server 2008 R2 nicht vom Tisch. Microsoft liefert die Verbesserungen jedoch innerhalb eines Hotfixes nach, sodass man auch dort Backups im OPC-Format anlegen kann.

Hinzu kommen noch eine ganze Reihe weiterer Verbesserungen. Ein Einspielen lohnt sich also ggf. trotz der endlichen Laufzeit der Systeme.

 

„Do you trust this printer?“ trotz konfigurierter „Point and Print Restrictions“

Unsere Kollegen vom Client Service haben erfahren müssen, dass Security Update KB3170455 die mittels Gruppenrichtlinie konfigurierten Einstellungen der „Point and Print Restrictions“ ad absurdum führt.

Microsoft beschreibt den Patch wie folgt:

„Dieses Sicherheitsupdate behebt Sicherheitsanfälligkeiten in Microsoft Windows. Das größere Sicherheitsrisiko könnte die Remoteausführung von Code ermöglichen, wenn ein Angreifer einen Man-in-the-Middle-Angriff (MiTM) auf einer Arbeitsstation oder einem Druckserver ausführen oder einen nicht autorisierten Druckserver im Zielnetzwerk einrichten kann.“

Nach der Installation des Updates ignoriert ein Windows Client die dort getätigten Einstellungen, fragt ob man dem Drucker vertrauen würde und bittet zu alledem noch um administrative Berechtigungen, um den Treiber installieren zu können.

image002

Es scheint dabei jedoch nur Druckertreiber zu erwischen, die noch nicht „Packaged“ sind, primär also ältere Druckertreiber. Neuere Druckertreiber, die schon im neuen Format gepackt wurden, werden weiterhin ordnungsgemäß ohne Abfrage installiert. Das Thema ist auch schon im Microsoft Forum angekommen und wird dort diskutiert.

Lets Encrypt – SSL-Zertifikat fürs Blog umgestellt

Die Verbindung zum Blog ist seit bestehen ausschließlich per TLS erreichbar und war bis vor wenigen Tagen noch per Class 2 Zertifikats von StartCom verschlüsselt. Die Initiative der Zertifizierungsstelle Lets Encrypt verschlüsselte Verbindungen zum Standard werden zu lassen, gefällt mir daher ausgesprochen gut. Es gibt im Web eigentlich keine Gründe mehr, nicht auf eine verschlüsselte Verbindung zu setzen. Eine Ausnahme gibt es oft noch bei Seiten mit eingebettetem Inhalt Dritter wie z.B. Foren, wo man jedoch die Login-Bereiche entsprechend absichern sollte.

Da mein StartCom-Zertifikat ohnehin im Januar ausgelaufen wäre und erneuert werden musste, habe ich mich gleich dazu entschieden auf Lets Encrypt zu wechseln. Die Installation auf einem Ubuntu Server 12.04 ist überraschend einfach und geht wie folgt. Da der Port 80 bei mir jedoch weiterhin in Benutzung ist, setze ich auf die Webroot-Methode und nicht auf den temporär laufenden LetsEncrypt-Webserver.

cd /opt/
git clone https://github.com/letsencrypt/letsencrypt
cd /opt/letsencrypt/

Sollte euch git fehlen, so ist dies mit folgendem Befehl zu installieren.

aptitude install git

Damit ist LetsEncrypt erstmal auf eurem Webserver installiert und einsatzbereit. Bevor wir uns jedoch ein Zertifikat ausstellen, sollten wir den Webserver entsprechend vorkonfigurieren. Ich gehe generell von einer laufenden SSL-Konfiguration aus, sollte diese nicht vorliegen verweise ich gerne auf eine kleine Anleitung meinerseits.

Wir starten mit der Einrichtung einer Config-Datei zur einfachen Definierung der Parameter für das neue Zertifikat. Diese Config-Datei benennen wir übersichtshalber nach unserem zu nutzenden Domänennamen und nutzen .cli als Suffix.

nano /etc/letsencrypt/Logikkreise.de.cli

Da ich nicht bereit bin meinen laufenden Webserver temporär zur Ausstellung eines Zertifikats zu beenden, nutze ich die Webroot-Methode zur Domänen-Validierung.


 This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Let's Encrypt with
# "--help" to learn more about the available options.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Always use the staging/testing server
# server = https://acme-staging.api.letsencrypt.org/directory

# Uncomment and update to register with the specified e-mail address
email = email@domain.tld

# Uncomment and update to generate certificates for the specified
# domains.
# domains = example.com, www.example.com
domains = domain.tld, www.domain.tld

# Uncomment to use a text interface instead of ncurses
# text = True

# Uncomment to use the standalone authenticator on port 443
# authenticator = standalone
# standalone-supported-challenges = tls-sni-01

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
authenticator = webroot
webroot-path = /path/to/webroot/

Nach Erstellen der Konfiguration können wir durch auskommentieren der Server-Zeile zwischen den Test/Staging-Server von Lets Encrypt und dem produktiven Server wechseln. Nur letzterer stellt euch ein vertrauenswürdiges Zertifikat aus, mit ersterem testet Ihr jedoch eure Konfiguration.

Nach Anlegen der Config-Datei erstellen wir für unseren Apache Webserver Symlinks zu den baldigen SSL-Zertifikaten. Dieser Schritt kann auch nach Erstellung der Zertifikate erfolgen.

Die Zertifikate von Lets Encrypt werden automatisch an folgendem Ort abgelegt.

/etc/letsencrypt/live/

 

Pro Domain wird Unterordner im genannten Pfad erstellt und darunterliegend die drei Zertifikate gespeichert. Das öffentliche (cert.pem), das private (privkey.pem), die Zertifikatskette (fullchain.pem). Die Pfade lauten also beispielsweise wie folgt:

/etc/letsencrypt/live/logikkreise.de/cert.pem /etc/letsencrypt/live/logikkreise.de/privkey.pem /etc/letsencrypt/live/logikkreise.de/fullchain.pem

 

Ich habe mich dazu entschieden diese Dateien nicht in das SSL-Verzeichnis vom Apache zu kopieren, sondern nur sogenannte Symlinks zu erstellen, also Verknüpfungen.

ln -s /etc/letsencrypt/live/domain.tld/cert.pem /etc/apache2/ssl/domain.tld.cert.pem ln -s /etc/letsencrypt/live/domain.tld/privkey.pem /etc/apache2/ssl/domain.tld.privkey.pem ln -s /etc/letsencrypt/live/domain.tld/fullchain.pem /etc/apache2/ssl/domain.tld.fullchain.pem

 

Sollten die Pfade widererwarten doch anders sein, so sind die Symlinks einfach anzupassen. Danach passen wir ebenfalls die Pfade innerhalb der Apache-Konfiguration an.

nano /etc/apache2/sites-enabled/domain.tld SSLEngine on SSLCertificateFile /etc/apache2/ssl/domain.tld.cert.pem SSLCertificateKeyFile /etc/apache2/ssl/domain.tld.privkey.pem SSLCertificateChainFile /etc/apache2/ssl/domain.tld.fullchain.pem

 

Nach dem Abspeichern der Konfiguration können wir uns endlich das Zertifikat von Lets Encrypt ausstellen lassen.

/opt/letsencrypt/letsencrypt-auto certonly -c /etc/letsencrypt/domain.tld.cli

 

Ein erfolgreiches Ausstellen der Zertifikate wird euch mit einer entsprechenden Meldung quitiert. Startet im Anschluss euren Apache Service einmal durch und prüft durch Besuchen eurer Webseite ob das neue Zertifikat korrekt eingebunden wurde.

service apache2 restart

Ein korrekt eingerichtetes Zertifikat sieht wie folgt aus:

Zertifikat

Windows Store: Update auf Windows 8.1 nicht möglich

Ich habe im Zuge der Veröffentlichung von Windows 10 vor kurzem eine komplette Neuinstallation meines privaten Primär-Rechners durchgeführt. Gestartet bei meiner damals gekauften Windows 8.0 Pro DVD, mit einem Upgrade auf Windows 8.1 über den Windows Store und gefolgt von Windows 10.

Leider wollte trotz sauberer Neuinstallation der Windows Store das Windows 8.1 Upgrade nicht installieren und mein Upgrade-Pfad zu Windows 10 wurde blockiert. Die Lösung des Problems ist die schlicht Neuinstallation / Reparatur vom Windows Store.

Man gibt dazu den folgende Befehl in eine administrativ gestartete PowerShell-Sitzung ein:

Add-AppxPackage -DisableDevelopmentMode -Register $Env:SystemRoot\WinStore\AppxManifest.XML

Sollte der Befehl aufgrund der ExecutionPolicy nicht erlaubt sein, ist folgender Befehl vorzuziehen. Der zweite Befehl stellt den Wert wieder auf die „sichere“ Variante und ist nach einem funktionierenden Windows Store auszuführen.

PowerShell -ExecutionPolicy Unrestricted

PowerShell -ExecutionPolicy RemoteSigned

Mozilla Firefox – Suchmaschinen-Feld aus neuem Tab entfernen

Ich bin eigentlich ein Freund von Opera 12, leider wurde der Browser ja eingestellt und dem Neustart mit Blink fehlen noch allerhand Funktionen, die Ihn mit seinem Vorgänger ebenbürtig machen würde. Drum habe ich, um mit der Zeit beim Thema Surfgeschwindigkeit nich gänzlich abgehängt zu werden, mich an den Firefox gewöhnen und mir mit ein paar Extensions ein wenig Opera-Flair verschaffen müssen.

Was mich bis zuletzt jedoch immer wahnsinnig gemacht hat ist das große Suchmaschinen-Feld innerhalb eines neuen (SpeedDial)-Tabs. Dieses kann man aber zum Glück relativ einfach ausblenden. Die Lösung dazu habe ich auf askvg.com gefunden und habe nur hinzuzufügen, dass man den Ordner „chrome“, sollte er nicht vorhanden sein, einfach erstellen kann. Firefox wird diesen und die darin befindlichen Dateien dann automatisch nutzen.