This article also available in English at LinkedIn Pulse: „Backing up BitLocker recovery keys afterwards in Active Directory with PowerShell„.
Ein typisches Problem, ein mit BitLocker verschlüsselter Rechner streikt und fragt nach dem Recovery Key. „Kein Problem, die GPO sagt die sind im AD gespeichert“. Soweit die Theorie der meisten Umgebungen die BitLocker ohne Management Lösungen wie Microsoft BitLocker Administration and Monitoring (MBAM) einsetzten. Doch meisten kommt dann das böse Erwachen…
Ein Blick ins Active Directory und es sind keine Informationen da!
Warum die BitLocker Wiederherstellungsschlüssel nicht im Active Directory zu finden sind
Die Gründe sind verschieden, aber die häufigsten drei sind:
- BitLocker Drive encryption by OEM
- Fehlerhafte Konfiguration
- Verbindungsprobleme
Besonders möchte ich hier auf die „Böse“ Verschlüsselung durch die OEM eingehen, da mich diesen Thema sehr oft in dem Zusammenhang beschäftigt.
BitLocker Verschlüsselung durch den Hersteller / OEM
Wie einige wissen, ich arbeite bei Dell Technologies, und so lese ich oft in den TechNet Foren „Dell/Lenovo/HP/… hat meinen Rechner Verschlüsselt und ich kann den nicht wiederherstellen“. Ja, der böse Hersteller war es, und das nur weil wir so Gemein sind.
Spaß beiseite, das liegt nicht an den OEM’s das ist eine Vorgabe von Microsoft, das der Hersteller das schöne „Windows 10“ Aufkleberchen drauf machen darf. Diese Funktion heißt „BitLocker automatic device encryption“ und ist aus Sicht von Microsoft eine Sicherheitsfunktion.
Wenn die Hardware die Funktion unterstützt, was eigentlich alle aktuellen Geräte tun, und man sich mit einem Microsoft Account oder einem Azure AD Benutzer bei der Out-of-the-Box Experiance (OOBE) anmeldet, verschlüsselt BitLocker schon in dem Moment. Da in der OOBE das Gerät noch nicht in der Domäne ist, greifen auch noch keine Policies. Dies betrifft auch Autopilot Geräte! Somit wird auch die Verschlüsselung nur nach Standarteinstellungen erfolgen.
Die Informationen speichert das Gerät dann im AzureAD und in dem Microsoft Konto mit dem sich angemeldet wurde.
Es kann auch vorkommen, das die Verschlüsselung zuschlägt wenn die Geräte über Richtlinien einem Hybrit-AD Join, also dem Hinzufügen zu einer AzureAD zusätzlich zur lokalen Active Directory Domäne erfolgt.
Mehr zu dem Thema: BitLocker drive encryption in Windows 10 for OEMs | Microsoft Docs.
Wie kann man BitLocker automatic device encryption bei einer MDT Task Sequenz unterbinden?
Dazu muss in der CustomSettings.ini der Eintrag „BDEDisablePreProvisioning“ gesetzt werden.
Wie kann man BitLocker automatic device encryption in der Registry abschalten?
Dafür gibt es einen entsprechenden Schlüssel. Je nach Szenario muss dieser allerdings auch schon in der WinPE Phase gesetzt sein. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\BitLocker Value: PreventDeviceEncryption equal to True (1)
Wie kann ich mit der PowerShell die Schlüssel ins Active Directory sichern?
Oftmals liegt das Kind halt im Brunnen. Was nun? Möglichkeit eins ist Entschlüsseln und mit den richtigen Einstellungen neu verschlüsseln. Das muss ich auch auf jeden Fall machen, wenn ich 256 Bit Verschlüsselung machen möchte und ich in die Automatische Verschlüsselung gelaufen bin. Daran führt dann kein Weg vorbei.
Jetzt kann ich aber mit den Einstellungen leben und möchte nur sichergehen, dass die richtigen Informationen gesichert wurden. Am besten ohne an alle Rechner zu müssen. Das geht mit etwas PowerShell und dem guten Manage-BDE Befehl.
Hürden des Manage-BDE
Das Kommandozeilen Programm Manage-BDE ist leider übersetzt.
Das bedeutet die Zeile nach der gesucht werden muss und der Wert unterscheiden sich in jeder Sprache. In meinem Musterskript sind bereits die Werte für Deutsch und Englische Betriebssysteme enthalten. Wer andere Sprachen im Einsatz hat, schreibt mir bitte die Länder-Locale und die Zeile in die Kommentare, ich erweitere dann das Skript.
Wichtig ist das, damit wir auch die Richtigen Laufwerke erwischen wenn wir über Manage-BDE die ID des Laufwerks abfragen.
Andere Stolpersteine
Was oftmals auch ein Problem sind, sind falsche Konfigurationen in Gruppenrichtlinien oder auf dem Client. Damit das nicht passiert, sollte die Registry einmal die richtigen Einstellungen mit im Skript gesetzt bekommen. Da Manage-BDE eh lokale Administrator Rechte benötigt, können wir auch in die Registry schreiben. Nicht vergessen, danach die Keys löschen und mit einem GPUPDATE wieder die richtigen Einstellungen anwenden lassen.
Das Skript
Hinweise zu Programm- und PowerShell Code
Der hier enthaltene Code dient als Beispiel. Ich übernehme keine Garantie, Gewährleistung oder Support für den Code oder Bestandteile. Verwendung des Codes erfolgt auf eigene Gefahr.
Ich empfehle immer sich die Skripte vor der Verwendung genau anzuschauen, was sie wirklich tun.
Der Code
<# .SYNOPSIS Upload BitLocker recovery information to Active Directory, if they not already exist. .DESCRIPTION Upload BitLocker recovery information to Active Directory, if they not already exist. WARNING: While the manage-bde Output is localized, this will only work on English and German Windows 10 devices. .EXAMPLE C:\PS> Update-BitLockerRecovery.ps1 .EXAMPLE C:\PS> Update-BitLockerRecovery.ps1 -locale "de-DE" .PARAMETER locale Language code of the OS, if not set the script will use "GET-WinSystemLocale" for autodetection .PARAMETER procstate String to determin the protection state based on the localized output of "manage-bde -status" .PARAMETER procstatepat Pattern to determin the if the protection state based on the localized output of "manage-bde -status" is enabled .PARAMETER adcheck Check Active Directory and shows the key. Require Active Directory PowerShell module installed and Domain Admin permissions .NOTES Author : Fabian Niesen (www.fabian-niesen.de) Filename : Update-BitLockerRecovery.ps1 Requires : PowerShell Version 3.0 Version : 1.0.0 History : 1.0.0 FN 01/22/2021 initial version .LINKBitLocker Wiederherstellungs Keys nachträglich im Active Directory mit der PowerShell sichern> Param( [Parameter(Mandatory=$false, Position=0, ValueFromPipeline=$False)] [String]$procstate="", [Parameter(Mandatory=$false, Position=1, ValueFromPipeline=$False)] [String]$procstatepat="", [Parameter(Mandatory=$false, Position=2, ValueFromPipeline=$false)] [string]$locale = $((GET-WinSystemLocale).Name), [switch]$adcheck ) $ErrorActionPreference = "Stop" If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { $arguments = "& '" + $myinvocation.mycommand.definition + "'" Start-Process powershell -Verb runAs -ArgumentList $arguments Break } switch($locale){ "de-DE" {$procstate = "Schutzstatus" ; $procstatepat = "Der Schutz ist aktiviert" ; Write-Verbose "Locale set to de-DE"} "en-EN" {$procstate = "Protection" ; $procstatepat = "Protection On" ; Write-Verbose "Locale set to en-EN"} Default {IF ($procstate -eq "" -or $procstatepat-eq "") { Write-Error -Message "Locale not prefinied in script! Please use parameter procstate and procstatepat. Please execute >Get-Help .\Update-BitLockerRecovery.ps1 -Detailed<" -Category NotImplemented }} } Try { New-Item -Path HKLM:\SOFTWARE\Policies\Microsoft -Name FVE } Catch {Write-Warning "Registry path already exists"} Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSRecovery -Value 1 -Type DWord -Force; Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSManageDRA -Value 1 -Type DWord -Force; Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSRequireActiveDirectoryBackup -Value 0 -Type DWord -Force; Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSActiveDirectoryInfoToStore -Value 1 -Type DWord -Force; Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSActiveDirectoryBackup -Value 1 -Type DWord -Force; Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSHideRecoveryPage -Value 0 -Type DWord -Force Get-PSDrive -PSProvider FileSystem | ? { !($_.DisplayRoot -ilike "\") } | % { $root = $_.Root # Fetch the drive letter or mount point if ($root -ilike "\") { $root = $root.substring(0, $root.length - 1) } # Remove trailing backslash [string] $status = (manage-bde -status $root) | Select-String -Pattern $procstate Write-verbose "Status: $status" if ($status -ilike $procstatepat) { [string] $id = (manage-bde -protectors -get $root -Type recoverypassword) | Select-String -Pattern ID $id = $id.Replace("ID: ", "").Trim() Write-verbose "ID: $id" manage-bde -protectors -adbackup $root -id $id sleep -Seconds 10 } } Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSRecovery -Force; Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSManageDRA -Force; Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSRequireActiveDirectoryBackup -Force; Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSActiveDirectoryInfoToStore -Force; Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSActiveDirectoryBackup -Force; Remove-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\FVE -Name OSHideRecoveryPage -Force Write-Verbose "Setting back GPO Settings" GPupdate.exe /Target:Computer /Force if ($adcheck -eq $false ) { try { Import-Module ActiveDirectory } catch { Write-Warning "ActiveDirectory Module ist missing. Please install for local check" break } Write-Output "Wait 30 sec to process and AD sync" sleep -Seconds 30 $recoveryPass = Get-ADObject -Filter {objectclass -eq 'msFVE-RecoveryInformation'} -SearchBase $($env:COMPUTERNAME).DistinguishedName -Properties 'msFVE-RecoveryPassword' | where {$_.DistinguishedName -like "$id"} Write-Output "Stored Recovery Password in AD: $recoveryPass " }
Das Skript ist in der aktuellen Version auf GitHub erhältlich.
Die Kontrolle
Das Script hat den Parameter „adcheck“, der setzt aber das PowerShell Modul für das Active Directory und Domänen Administrator Rechte vorraus. Wer mich kennt, weis das ich kein Fan davon bin. Aber zu den Alternativen später.
Auf einem Domänen Kontrolle kann das mit der PowerShell wie folgt abgefragt werden:
Get-ADObject -Filter {objectclass -eq 'msFVE-RecoveryInformation'} -SearchBase $DistinguishedName -Properties 'msFVE-RecoveryPassword' | where {$_.DistinguishedName -like "*$id*"}
$DistinguishedName ist dabei der DN des Computer, zum Beispiel „DN=MeinPC,OU=Ja,OU=flache,OU=Struckturen,OU=im,OU=AD,DC=Waehren,DC=schoen“
Der Masseneinsatz des Skriptes
Es gibt verschiedene Möglichkeiten:
- Ausrollen über die Softwareverteilung, wenn vorhanden
- Über die Gruppenrichtline als Geplante Aufgabe zur sofortigen Ausführung
- Remote als PowerShell Skript mit LAPS
Hinweis zur Transparenz
Zum Zeitpunkt der Erstellung des Artikels arbeitete ich für Dell Technologies. Trotzdem spiegelt dieser Artikel meine rein persönliche Meinung wieder, und wurde nicht durch meinen Arbeitgeber in irgendeiner Weise gefördert, beeinflusst oder vergütet. #Iwork4Dell
Schreibe einen Kommentar