Securing LDAP
LDAP staat voor Lightweight Directory Access Protocol. LDAP is een open protocol en wordt gebruikt binnen diverse toepassingen. Het meest bekend is LDAP vanwege zijn integratie met Active Directory. Het LDAP protocol wordt meestal ingezet om informatie over een organisatie en bijbehorende gebruikers op te slaan. LDAP is een flexibele oplossing voor het definiëren van een entiteit en bijbehorende eigenschappen. Het nadeel van LDAP is dat LDAP gegevens in plain-text (leesbaar) over het netwerk verstuurd. LDAP is op verschillende manieren te beveiligen namelijk met LDAP Signing, Channel Binding en LDAP over SSL ofwel LDAPS. In deze post gaan we bekijken hoe LDAP werkt en hoe het LDAP verkeer te beveiligen is.
Mocht je mijn vorige post over de LDAP fundamentals nog niet gelezen hebben… dan is het raadzaam om dat even te doen alvorens je deze post gaat lezen. De post zal meer contect geven aan “LDAP” als protocol en zal eveneens een aantal zaken uit deze post verduidelijken.
De vraag om LDAP over een veilig kanaal te laten verlopen wordt nog sterker nu Microsoft heeft aangegeven om in 2020 een patch uit te brengen waarop insecure LDAP standaard word uitgeschakeld en LDAP Signing wordt ingeschakeld. Dit betekend dat LDAP op een niet-versleutelde manier actief geactiveerd moet worden. Momenteel is dit andersom. Microsoft brengt deze veiligheidsstandaard op 2 verschillende momenten:
1. De Windows Updates van maart 2020 hebben nieuwe auditgebeurtenissen, extra logboekregistratie en een nieuwe toewijzing van groepsbeleidswaarden toegevoegd. Deze toevoegingen maken LDAP Channel Binding en LDAP Signing mogelijk.
2. Microsoft zal later in 2020 tijdens de serverupgrades LDAP Signing en LDAP Channel Binding inschakelen.
Het is dus tijd om actie te ondernemen. Maar hoe? Moeten we LDAP Signing gebruiken? Channel Binding of LDAPS? Laten we deze technieken even kort uitleggen:
LDAPS – LDAP over SSL:
Zoals al gezegd werkt LDAPS door eerst een veilige SSL (Secure Socket Layer) tunnel op te bouwen en hierover het LDAP verkeer te sturen. LDAPS werkt over een alternatieve poort, namelijk poort 636.
SSL- en TLS-protocollen bestaan binnen het TCP/IP OSI model binnen de hogere protocollen, zoals LDAP. Dit zorgt ervoor dat wanneer een server geconfigureerd is om zichzelf te authentiseren middels SSL bij een SSL client ze beide een veilige verbinding op kunnen bouwen. SSL / TLS-geactiveerde LDAP-clients kunnen gebruik maken van standaard cryptografische technieken zoals openbare sleutels om het certificaat en de openbare ID van een server als “geldig” te valideren waarna een verbinding tot stand gebracht kan worden.
Deze techniek vereist een certificaat welke aanwezig is op alle clients die gebruik moeten kunnen maken van LDAP. Dit mag een self-signed certificaat zijn of een publiek certificaat. Best-practice is om een publiek certificaat te gebruiken. Belangrijk is dat elke client het certificaat vertrouwd.
Het nadeel van LDAPS (636) is dat het gebruik maakt van SSL versleuteling op een separate TCP poort. SSL is al een aantal jaren verouderd en er zijn aanvallen bekend die niet zullen worden verholpen.
Voor LDAPS moet het certificaat aan 3 eisen voldoen:
- Het certificaat moet geldig zijn voor serververificatie. Dit betekent dat deze ook de “Server Authentication object identifier” (OID) moet bevatten (1.3.6.1.5.5.7.3.1)
- De Subject-naam of de voornaam in de Subject Alternative Name (SAN) moet overeenkomen met de Fully Qualified Domain Name (FQDN) van de hostmachine. Dus b.v. CN = “server001”.
- Het computeraccount van de hostcomputer moet toegang hebben tot de privésleutel
Wanneer het certificaat gegenereerd is en aan bovenstaande eisen voldoet zal LDAPS operationeel zijn. Let op, de client moet dit certificaat ook vertrouwen. Dit kan aardig wat handmatig werk opleveren bij niet-domein apparaten die toch gegevens ophalen via LDAP. Denk aan b.v. printers. Voor de domain-based deivces kun je verschillende technieken inzetten om het certificaat te deployen zoals group policy. Wanneer je hiermee veel problemen verwacht gebruik dan een commercieel certificaat. Controleer altijd of je apparaten overweg kunnen met LDAPS.
LDAP Signing:
LDAP Signing is onderdeel van de “Simple Authentication and Security Layer” ofwel de SASL layer van het LDAP protocol. SASL biedt verschillende mechanismen om de beveiliging van een LDAP-verbinding te verbeteren waaronder gebruikersauthenticatie, anti-tampering (ondertekenen van berichten) en vertrouwelijkheid (encryptie). Wanneer LDAP Signing ingeschakeld wordt kan dit van invloed zijn op oudere desktopclients en domeincontrollers die LDAP-signing niet ondersteunen. Er bestaan 3 niveaus van LDAP-signing:
- 0 – Niet vereist
- 1 – Sign alleen als beide partijen dit ondersteunen
- 2 – Altijd signen
LDAP Signing is verschilt sterk van LDAPS op de volgende punten:
- LDAP Signing bouwt een LDAP verbinding op bouwt over deze verbinding een TLS verbinding op. De default LDAP poort blijft hiermee 389.
- LDAP Signing heeft geen afhankelijkheid met een PKI infrastructuur.
De voordelen van LDAP Signing t.o.v. LDAPS is dat de communicatie met LDAP Singning over de normale poorten blijft gaan, dat er geen PKI certificaat nodig is en dat de installatie volledig met Group Policy (of register setting) in te stellen is.
LDAP Channel Binding:
LDAP Channel Binding is een afgeleide van EPA (Extended Protection for Authentication) voor HTTP en werkt door gebruik te maken van SSPI Extended Authentication Protection (EAP). LDAP Channel Binding zorgt ervoor dat NTLM relaying niet mogelijk is. NTLM relaying is het doorgeven van authenticatiegegevens naar andere services / poorten. NTLM is een challenge-response-protocol. Wanneer een client verbinding maakt krijgt deze van de server een zogenaamde “challenge”. De client reageert op de challenge door de challenge te versleutelen met zijn password hash. De server stuurt het antwoord vervolgens door naar een domeincontroller die ook over de password hash van de client beschikt. De domeincontroller vergelijkt de opgeslagen password hash van de gebruiker met de challenge en het antwoord van de server. Als deze berekeningen overeenkomen wordt de authenticatie als succesvol beoordeeld.
Bij NTLM-relaying komt het erop te neer dat een succesvolle authenticatie doorgespeeld wordt naar een andere service waardoor ineens toegang tot die service wordt verkregen. Stel je bijvoorbeeld voor dat een administrator op een link naar een bestandsshare klikt. Op dat moment verwacht zijn computer dat hij zich authentiseert bij een SMB-gebaseerde bestandsshare. Echter wordt deze succesvolle authenticatie op de achtergrond gerelayed naar de LDAP-interface van een domeincontroller. De aanvaller kan nu alle acties op AD uitvoeren zoals het aanmaken van een eigen admin account.
LDAP Channel Binding ofwel “NTLM channel binding tokens” voorkomen de “doorgifte” van authenticatiegegevens door deze te binden aan één afzonderlijk protocol. Hierbij worden dus feitelijk de transport layer en de application layer aan elkaar gekoppeld.
LDAP Signing en LDAP Channel Binding installeren
LDAP Signing heeft een aantal voordelen t.o.v. LDAPS. Soms heb je echter niet de keuze om al het verkeer te signen (Linux). In dat geval is LDAPS de beste (fallback) optie om het LDAP verkeer toch te beveiligen. LDAP Signing wordt vrij breed ondersteund, ook op niet-Windows OSen. Maar de ondersteuning buiten Windows OSen voor LDAP Channel Binding is zeldzaam. In de meeste gevallen zal het echter afdoende zijn om LDAP Signing en LDAP Channel Binding toe te passen om al het LDAP verkeer te beveiligen. Mocht je alle technieken willen implementeren dan is ook een combinatie van deze 3 mogelijk. De ene techniek sluit het andere niet uit.
Laten we specifiek kijken naar LDAP Signing en LDAP Channel Binding. De GPO / registersettings zijn van kracht op deze twee technieken:
LDAP Signing
GPO voor Domain Controller:
Computer Configuration - Policies - Windows Settings - Security Settings - Local Policies - Security Options - Domain controller: LDAP server signing requirements |
Register op domain controller:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LDAPServerIntegrity (DWORD) |
GPO voor client:
Computer Configuration - Policies - Windows Settings - Security Settings - Local Policies - Security Options - Network security: LDAP client signing requirements |
Register op client:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LDAPServerIntegrity (DWORD) |
LDAP Channel Binding
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LdapEnforceChannelBindings (DWORD) |
De implementatie kan naar mijn inschatting het beste als volgt gebeuren:
1. Zorg dat aan alle requirements voldaan is. Een belangrijke requirement voor LDAP Channel Binding is:
Wanneer LDAP Channel Binding wordt geactiveerd moeten alle clients minimaal beschikken over de volgende patch: https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2017-8563. Windows Server 2008 en oudere systemen moeten voor het toepassen van voorgaande patch ook voorzien zijn van de patches in de MS Security Advisory 973811.
Daarnaast is het belangrijk om te weten dat bij het doorvoeren van een LDAP registersettings geen reboot van de server nodig is. De setting is meteen actief.
Als aan de requirements is voldaan kunnen we de implementatie starten.
2. Allereerst moet logging ingeschakeld worden op de LDAP servers zodat we weten welke services LDAP verzoeken genereren (onbeveiligd). Deze logging schakelen we in door de volgende registry setting op de domaincontrollers aan te passen:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics\16 LDAP Interface Events |
Deze regkey bestaat standard niet en kunnen we instellen op op 5 niveau’s:
0 – Geen logging op uitzondering van kritische events en error events
1 – Minimaal, alleen high-level events worden gelogd
2 – Basic, alle normale logs worden gelogd
3 – Extensive, dit loglevel zorgt ervoor dat er additionele loginformatie verzameld worde van de basic logs.
4 – Verbose, alle events worden gelogd met uitzondering van debug informatie
5 – Internal, alle events worden gelogd inclusief debug informatie
Voor onze doelstelling kunnen we het niveau instellen op niveau 2. Laten we de regkey toevoegen op alle domain controllers:
Met CMD:
Reg Add HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics /v "16 LDAP Interface Events" /t REG_DWORD /d 2 |
Met Powershell:
New-ItemProperty -Path ‘HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics’ -Name “16 LDAP Interface Events” -Value 2 -PropertyType DWORD -Force |
Nadat logging is ingeschakeld kunnen de logboeken gecontroleerd worden op diverse eventlogs. De eventlogs waarop gelet moet worden zijn:
LDAP Signing
- 2886 – LDAP Signing is niet geactiveerd. Dit komt voor als de signing policy niet is ingeschakeld. Dit event wordt elke 24 uur gelogd en bij het opstarten en starten van de service v.a. loglevel 0.
- 2887 – Er hebben 1 of meerdere onveilige (simple) LDAP Bind plaatsgevonden. Dit komt voor als de signing policy niet is ingeschakeld. Dit event wordt elke 24 uur gelogd v.a. loglevel 0.
- 2888 – Er hebben 1 of meerdere onveilige (simple) LDAP Bind plaatsgevonden. Dit komt voor als de signing policy is ingesteld als “Require Signing”. Dit event wordt elke 24 uur gelogd v.a. loglevel 0.
- 2889 – Wordt gelogd wanneer een client geen LDAP Signing gebruikt voor binds op poort 389. Dit event wordt gelogd v.a. loglevel 2.
LDAP Channel Binding
- 3039 – De aangegeven client heeft een LDAP bind op proberen te zetten over SSL/TLS maar de bind is mislukt omdat er geen geldige CBT is aangeboden. Validatie mislukt. Deze log wordt bij elke gefaalde CBT validatie gelogd. Deze eventlog wordt gelogd v.a. loglevel 0.
- 3040 – Deze policy wordt elke 24 uur gelogd en laat zien hoeveel unprotected LDAP binds tot stand zijn gekomen. Deze eventlog wordt gelogd v.a. loglevel 0 als de policy is ingesteld op “Never”.
- 3041 – LDAP Channel Binding is niet geactiveerd. Dit komt voor als de LDAP channel Binding policy niet is ingeschakeld. Dit event wordt elke 24 uur gelogd en bij het opstarten en starten van de service v.a. loglevel 0.
3. We hebben de logging ingeschakeld op “2”. Nu gaan we de settings als volgt instellen:
- LDAP Signing optie 0 – (optie 0 = uit, optie 1 = enabled als beide partijen het ondersteunen en optie 2 = require signing)
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters" -Name "LDAPServerIntegrity" -Value 0
- LDAP Channel Binding optie 1 – Bind alleen als beide partijen dit ondersteunen
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "LdapEnforceChannelBindings" -Value 1
- GPO Network security: LDAP client signing = Negotiate signing
4. Nu is het zaak om de logboeken op alle LDAP servers in de gaten te houden en te controleren op de volgende logboekvermeldingen:
LDAP Signing: 2887
LDAP Channel Binding: 3039
Noteer alle mislukte LDAP sign & bind pogingen en achterhaal de clients. Probeer ervoor te zorgen dat deze clients op de juiste manier gaan signen en binden. Als dat niet lukt probeer dan LDAPS te configureren en deze clients te configureren over LDAPS waardoor ze op een andere poort (SSL) verbindingen, de verbinding relatief veilig is en LDAP Signing en LDAP Channel Binding niet enforced wordt.
5. Als alle apparaten afdoende geconfigureerd zijn stellen we de settings als volgt in:
- LDAP Signing optie 1 – Sign alleen als beide partijen dit ondersteunen
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters" -Name "LDAPServerIntegrity" -Value 1
- LDAP Channel Binding optie 1 – Bind alleen als beide partijen dit ondersteunen
- GPO Network security: LDAP client signing = Negotiate signing
Nu gaan we de logboeken nakijken op de logs:
LDAP Signing: 2889
LDAP Channel Binding: 3039
Achterhaal de problematische clients, probeer deze compatible te krijgen en gebruik LDAPS als dit niet mogelijk is.
6. Nu zijn we klaar om LDAP Signing volledig in te schakelen en dus stellen we de volgende zaken in:
- LDAP Signing optie 2 – LDAP Signing is verplicht
Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\NTDS\Parameters" -Name "LDAPServerIntegrity" -Value 2
- LDAP Channel Binding optie 2 – Channel Binding is verplicht
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" -Name "LdapEnforceChannelBindings" -Value 2
- GPO Network security: LDAP client signing = Require signing
Om eventuele calamiteiten te voorkomen kijk je de logboeken na op de volgende eventID’s:
LDAP Signing: 2888
LDAP Channel Binding: 3039
7. Om te testen of LDAP Channel Binding goed is ingeschakeld installeer je de “AD DS Admin Tools” en start je “ldp.exe”. Vervolgens maak je een connectie op poort 389 en kies je om een “simple bind” te maken. Geef hierbij correcte gebruikersgegevens op. Als Channel Binding actief is moet je de volgende foutmelding geretourneerd krijgen:
Ldap_simple_bind_s() failed: Strong Authentication Required |
*Simple Bind is een binding met gebruikersnaam en wachtwoord. De vereiste SASL Bind ondersteund meerdere authenticatiemethodes tegen LDAP waaronder Negotiate, Kerberos, NTLM en Digest.
Om de server gemakkelijk op LDAP Signing events te monitoren kun je een custom event log aanmaken of de “LDAP Signing Events Custom View.xml” importeren in de eventlogs zodat je snel een overzicht krijgt van de signing events op die domaincontroller. De “LDAP Signing Events Custom View.xml” is hier te vinden: https://github.com/russelltomkins/Active-Directory. Wil je echter meteen alle LDAP Signing Events en Channel Binding events inzichtelijk hebben download dan hier mijn custom Event Viewer XML.
We kunnen de signing events ook als volgt exporteren met dit Powershell script. Dit script exporteert alle “Directory Events” maar deze kunnen we handig sorteren in de CSV export:
#Export LDAP Signing event logs – Jarno Baselier Set-Variable -Name EventAgeDays -Value 7 #Events from the last 7 days Set-Variable -Name CompArr -Value @("DC01", " DC02", " DC03", " DC04") # Replace with server names Set-Variable -Name LogNames -Value @("Directory Service") # Check the Directory Service logs Set-Variable -Name EventTypes -Value @("Error", "Warning") # Loading only Error events and Warning events Set-Variable -Name ExportFolder -Value "C:\Temp\" $el_c = @() #consolidated error log $now=get-date $startdate=$now.adddays(-$EventAgeDays) $ExportFile=$ExportFolder + " LDAP-Signing-Errors-Last-7days-" + $now.ToString("yyyy-MM-dd---hh-mm-ss") + ".csv" # we cannot use standard delimiteds like ":" foreach($comp in $CompArr) { foreach($log in $LogNames) { Write-Host Processing $comp\$log $el = get-eventlog -ComputerName $comp -log $log -After $startdate -EntryType $EventTypes $el_c += $el #consolidating } } $el_sorted = $el_c | Sort-Object TimeGenerated #sort by time Write-Host Exporting to $ExportFile $el_sorted|Select EntryType, TimeGenerated, Source, EventID, MachineName | Export-CSV $ExportFile -NoTypeInfo #EXPORT Write-Host Done! |
Om snel te testen welke LDAP events er voorkomen in de logboeken is het raadzaam om een script te gebruiken. Dat scheelt veel handmatig zoekwerk. Het volgende script kan hiervoor perfect gebruikt worden: Query-InsecureLDAPBinds.ps1 (https://github.com/russelltomkins/Active-Directory).
Het defaultcommando is als volgt:
.\Query-InsecureLDAPBinds.ps1 -ComputerName %domaincontroller% |
Standaard draait het script met een periode van 24 uur, maar dit kun je veranderen met het “hours” commando.
Laten we een nieuw Powershell script maken waarin we het LDAP Signing Error laten draaien en het LDAP Channel Binding script voor 4 servers over de laatste 7 dagen. Op die manier kunnen we met 1 script alle relevante content van alle servers verzamelen. Dit script ziet er als volgt uit:
cd C:\Users\administrator\Desktop\Temp-Scripts .\Query-InsecureLDAPBinds.ps1 -ComputerName dc01.jarnobaselier.nl -Hours 168 # 1 week .\Query-InsecureLDAPBinds.ps1 -ComputerName dc02.jarnobaselier.nl -Hours 168 # 1 week .\Query-InsecureLDAPBinds.ps1 -ComputerName dc03.jarnobaselier.nl -Hours 168 # 1 week .\Query-InsecureLDAPBinds.ps1 -ComputerName dc04.jarnobaselier.nl -Hours 168 # 1 week .\Query-LDAP-Signing-Events.ps1 #Query all LDAP Signing Events |
Ik prefereer het gebruik van de Powershell scripts boven het gebruik van de logboeken omdat de Powershell scripts een handige CSV genereren en gemakkelijk te schedulen zijn. Dit schedulen doen we als volgt:
Zorg er dus voor dat je bij : Program” de PowerShell.exe aanroept en bij de argumenten de volgende 2 argumenten geeft:
-ExecutionPolicy ByPass -File C:\Users\adminjarno\Desktop\Quiry LDAP Signing Errors and Insecure LDAP Binds – All DC’s.ps1
Dus:
-ExecutionPolicy ByPass
-File %full-path-to-script%\Quiry LDAP Signing Errors and Insecure LDAP Binds – All DC’s.ps1
Conclusie
Als het goed is moet je nu voldoende informatie hebben om LDAP te begrijpen en te beveiligen. Het is niet gemakkelijk om alle relevante informatie te combineren tot een degelijke oplossing en een goed plan van aanpak, zeker door de gefragmenteerde informatie die online te vinden is. Ik hoop je met deze post een stukje op weg geholpen te hebben.
Vond je deze post interessant dan heb ik een klein verzoekje aan je! Ik maak mijn posts met veel plezier maar jullie zijn de reden dat ik enthousiast blijf om ze te schrijven. Wil je deze post s.v.p. verder delen op je website of sociale kanalen? Geef hem even een like of stuur me een leuk berichtje. Dat wordt ontzettend gewaardeerd!! Dankjewel!