Windows 2012 a Windows 8 přišly s technologiemi jako jsou group managed service accounts (gMSA), dotažený DNSSEC (neboli secure DNS), soubory certifikátů se soukromým klíčem (private key), tedy PKCS #12 PFX soubory šifrované pro celou uživatelskou skupinu (neboli group protected PFX files), nebo třeba BitLocker šifrování pro sdílené diskové oddíly na failover clusteru (neboli BitLocker protected failover cluster volumes).
Jsou to všechno úplně jiné bezpečnostní technologie. Mají ale jednu společnou vlastnost, pro kterou bylo potřeba nejprve dodat podporu do Active Directory (AD DS). Všechny tyto technologie pracují na více počítačích a to i současně. Všechny používají nějaký tajný šifrovací klíč (secret key), který musí být na všech těch počítačích k dispozici.
Podívejme se na zrychleně jednotlivé typy a jejich klíče. Potom nás bude zajímat jak se to sakra sdílí. Zjednodušeně řečeno, někde se povalují klíče. Musíme zajistit, aby jen určitá skupina počítačů (nebo uživatelů) byla schopna si je přečíst, neboli použít. Nikdo jiný to nesmí být schopen udělat. A současně nechceme, aby se ty klíče přímo ukládaly v AD (jasné, ne? PFX je prostě jenom soubor).
Účty typu group managed service account (msDS-GroupManagedServiceAccount)
Tohle jsou v podstatě normální uživatelské účty, které ovšem nejsou obvyklého typu (class) user a mají určité výhody. Zvláště automatickou změnu hesla. Od Windows 2012 je můžete použít pro běh služeb (service), naplánovaných úloh (scheduled task), nebo IIS fondů aplikací (app pool). Účty se vytváří v Active Directory LDAPu pouze pomocí PowerShell příkazu New-AdServiceAccount. Nějaké informace můžete dostat zde, ale není to až tak úplně do detailu, jak mě osobně zajímalo.
V případě group managed service account (group MSA, uživatelské objekty typu msDS-GroupManagedServiceAccount) se jedná prostě o heslo (password) toho účtu. Tedy symetrický klíč v podstatě (symmetric key). Na každém serveru, kde má být daný skupinový účet spravované služby použit, musí být jeho heslo známo v plné formě (plain text, clear text). O tom, že účty služeb, naplánovaných úloh a IIS app poolů mají hesla uložena v plné formě jsem tu už psal (další věci zde a zde). V případě těchto účtů tomu není jinak. Mají jen dvě výhody.
Zaprvé se jim heslo mění samo - mění se to zvláštním způsobem, pobavíme se o tom později - pravidelně jednou za třicet dnů. Pokud tedy nezměníte frekvenci změny parametrem ManagedPasswordIntervalInDays (AD attribute msDS-ManagedPasswordInterval). Zadruhé pro ně LSA na serverech nedělá v případě Kerberos ověření kontrolu zvanou PAC validation (k tématu PAC a jeho kontroly jen okrajově zde a zde a tady).
Znamená to tedy, že všechny počítače (proto group MSA), na kterých je takový účet zadán pro běh nějaké služby, musí být to heslo k dispozici. Daný počítač si ho musí od někud stáhnout. Stáhne si ho rovnou z Active Directory databáze. Seznam počítačů, které si mohou heslo účtu přečíst, se konfiguruje pomocí parametru PrincipalsAllowedToRetrieveManagedPassword (ADDS attribute msDS-GroupMSAMembership).
Je to normální účet uživatele/počítače, takže se samozřejmě v AD ukládá jeho normální hash (nt-hash MD4, digest hash MD5, aes hash SHA-1 apod.). Ale navíc se v atributu msDS-ManagedPassword pamatuje přímo jeho heslo v plné formě. Je to sice constructed (computed) atribut, ale o tom až za chviličku. Počítače, které to mají dovolené, si to heslo prostě odtud načtou v plné formě. A to je právě ta divnost, že?
Už teď dopředu můžeme říct, že atribut msDS-ManagedPassword je opravdu jen constructed (computed) atribut. To znamená že v databázi NTDS.DIT ve skutečnosti není přímo uložen. Pokud se podíváte na gMSA pomocí repadmin /showobjmeta, dozvíte se, že jediné, co je tam ve skutečnosti uloženo je atribut msDS-ManagedPasswordId. Hodnota tohoto atributu není nijak pořádně chráněna, atribut není confidential, ani na něm nejsou žádná speciální oprávnění. Prostě se normálně replikuje i do RODC, a kdokoliv kdo to má dovoleno, si ho může přečíst. Z něho se zjišťuje heslo toho účtu.
Poznámka: jen pro úplnost, je zajímavé, že se to dokonce tváří spíše jako počítačový účet - je to odvozeno od třídy (class) computer, atribut sAMAccountType obsahuje hodnotu 805306369 = MACHINE_ACCOUNT, primární skupinu (primaryGroupId) má Domain Computers a i atribut userAccountControl obsahuje bit 0x1000 = 4096 = WORKSTATION_TRUST_ACCOUNT.
Technologie secure DNS, neboli DNSSEC
V případě DNSSEC jde o zone master key signing key (KSK) - tedy klíč, kterým se v podstatě podepisují (digital signature) záznamy v DNS zóně (zone). Sice nepřímo, prostředníctvím dalších klíčů - zone signing key (ZSK) - ale přesto bezpečnost stojí na onom master klíči. Jedná se o RSA, nebo o ECDSA soukromý klíč (private key).
Podpisový klíč je uložen opět v Active Directory, opět v plné formě, samozřejmě. Je to obsah objektu typu dnsZone a jeho atributu msDNS-SigningKeys. Tohle je v příslušné DNS application partition, například v DomainDnsZones, nebo v celo-forestové ForestDnsZones. K tomu je tam ještě jeden atribut msDNS-SigningKeyDescriptors. Oba atributy jsou normálně nezabezpečené, normálně replikované i do RODC a nemají žádná speciálnější oprávnění.
Není to nebezpečné? Všimněte si také, že tyto klíče, podle uložení záznamů zóny (zone records), musí být schopen dostat libovolný DNS server na libovolném DC z celého forestu.
Ochrana privátního klíče v souboru PFX pro uživatelskou skupinu (group protected PFX)
Pokud máte Windows 8, nebo Windows 2012 a novější, pokud exportujete certifikát i se soukromým klíčem (private key) do formátu PKCS12, tedy do souboru PFX (někdy i P12), musíte ho tam nějak zašifrovat. Buď prostě zadáte heslo, jako kdykoliv dříve. Nebo jen vyberete, že ho má být schopna dešifrovat nějaká Active Directory skupina. A je to. Bez zadávání hesla. A přitom je to šifrováno nějakým symetrickým klíčem.
A tenhle soubor se vám bude povalovat kdekoliv na libovolném počítači v celém forestu. A zase to musí být bezpečně chráněno jen pro danou AD skupinu. Musíme počítat také s tím, že se její členství bude občas měnit.
V tomto případě je také důvod, aby ty klíče nebyly přímo uloženy v AD. Takových PFX souborů může existovat tisíce, nebo milióny a proč bychom tím zahmyzovali obsah LDAPu? Navíc kdo by řešil, jestli jsou ty klíče ještě potřeba, nebo zda už ten PKCS 12 soubor vůbec neexistuje?
Ve skutečnosti je seznam autorizovaných skupin (descriptor) i ten dešifrovací symetrický klíč uložen přímo v tom PFX souboru.
BitLocker a oddíly sdílených úložišt na failover cluster
Opět velice podobně. Máte několik členů klastru (failover cluster). Všechny tyhle počítače (node) mají připojen nějaký společný "disk". Všechny do něho umí samy nekontrolovaně zapisovat (cluster shared volume). Když to chcete mít zašifrované pomocí BitLocker Drive Encryption (BDE, FVE), všechny node musí mít na to klíč. Symetrický (symmetric key) AES klíč. Jak to budou sdílet?
Přímo na zašifrovaném oddílu je jeho dešifrovací klíč spolu s popisovačem (descriptor), který říká, že pouze účet failover clusteru může klíč používat.
Rekapitulace požadavků
Všechny ty služby mají svoje tajné informace u sebe při ruce. Uloženy podle vlastní logiky. Některé v LDAPu, některé v souboru, BitLocker to má v metadatech zašifrovaného oddílu. Někdo jiný by to mohl mít v registrech. Nebo napsané na papírku. Prostě každý si uloží svoje tajné klíče.
K tomu tam je vždycky ještě nějaký popisovač (descriptor), který určuje skupiny, nebo uživatelské účty, které ta tajná data mohou dostat, neboli používat.
Musíme zajistit, aby tajná data nešla jen tak přečíst. A nesmíme dovolit, aby někdo změnil ten popisovač - descriptor.
Řešení v podobě centrálního klíčového serveru na Windows 2012
Windows 2012 přichází s novou službou (Windows service) nazvanou Microsoft Key Distribution Service (kdssvc), která je realizována jako kdssvc.dll do lsass.exe procesu. Služba se instaluje jako součást AD DS (Active Directory Domain Services) role. Je to RPC služba (B9785960-524F-11DF-8B6D-83DCDED72085), která se startuje Manual (Triggered), tedy zapne se sama až si o to libovolný klient požádá přes port TCP 135 (RPC endpoint mapper). Dokonce k tomu existují i dvě výchozí výjimky ve Windows Firewall.
Nijak to nezávisí na domain functional level (DFL), ani forest functional level (FFL) - některé další věci, které nejsou závislé na funkční úrovni jsou třeba zde.
Tahle služba realizuje nové Group Data Protection API (DPAPI-NG, neboli CNG DPAPI). To je novější rozšíření a obdoba DPAPI, což procuje jen lokálně (tohle používá třeba SharePoint k ochraně passphrase). Dokumentace se dá najít v Open Protocol Specifications. Jmenuje se to také CNG DPAPI, protože je to postavené nad novým Cryptography Next Generation API. Není moc programů, které by CNG používaly, ale ono to není ve skutečnosti potřeba, rozhodně ne kvůli group MSA.
Funguje to velice jednoduše. Služba Microsoft Key Distribution Service běží jen na Windows 2012 a novějších DC. Služba má přímo v Active Directory, v Configuration oddíle (partition) uložen svůj root master key (někdy taky KDS root key). Nachází se to tady:
CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=
CN=Master Root Keys
Je tam jeden, nebo více, objektů typu msKds-ProvRootKey, které mají svoje tajná data v atributech msKds-KDFParam, msKds-SecretAgreementParam a msKds-RootKeyData. Je to v Configuration oddíle, takže je to replikováno na všechna DC v celém forestu. Tyto tři citlivé atributy jsou ve schematu označeny pomocí searchFlags jako CONFIDENTIAL a RODC_FILTERED. Znamená to, že se nereplikují do RODC. Jejich hodnotu může také číst pouze uživatel, který na ně má oprávnění zápisu - to je ta vlastnost confidential. Taková oprávnění má pouze SYSTEM, Domain Admins z forest root domain a Enterprise Admins. Tudíž je to vcelku dobře chráněno.
Pokud tam ještě žádný takový root master key není vytvořen, je potřeba ho založit ručně (nebo se založí sám), pomocí Add-KdsRootKey. V podstatě potřebujete jen jedne takový root key. Ale můžete jich mít více. Každý root key má jiné parametry, jako jestli to je RSA, nebo ECDSA klíč, případně se může lišit svou bitovou délkou.
Je zajímavé, že kvůli gMSA si ten PowerShell musíte zavolat sami ručně, zatímco ochránit PFX, nebo DNSSEC zónu a BitLocker jde samo od sebe. Klíč tam vznikne prostě sám od sebe.
Jestli tam klíč už máte se můžete buď normálně podívat, například přes ADSI Edit, nebo byste měli vidět následující událost v KdsSvc logu na jednom z vašich Windows 2012 a novějších DC:
Log: Application and Service Logs/Microsoft/Windows/KdsSvc/Operational
Event Id: 4004
Event Type: Information
Event Source: KdsSvc
Message: Group Key Distribution Service created the first root master key in AD. The key ID is ...
Služba Key Distribution Service je přístupná přes RPC (například lsass named pipe). Spolu s původním DPAPI to nabízí služby jako protect key a protect secret a unprotect key a unprotect secret. Sama služba dělá ve skutečnosti jenom generování konkrétních skupinových klíčů (generates group key) ze svého root master key. Ale precizní detaily si můžete přečíst v normě. To pro nás není až tak podstatné.
V podstatě a technicky velmi zjednodušeně to funguje takto:
- chci ochránit nějaká tajná data (secret) tak, že se k tomu dostane jen nějaká konkrétní skupina (protect secret)
- vygeneruji si seznam skupin (SIDů, tedy security descriptor), které se k daným tajným datům mohou dostat, tohle se nazývá descriptor
- třeba DNSSEC tam dává skupinu Domain Controllers (RID 516), pokud se jedná o zónu v DomainDnsZones, nebo SID Enteprise Domain Controllers (S-1-5-9)
- failover cluster tam dává svůj klastrový virtuální účet (virtual cluster account)
- group managed service account tam dává vcelku překvapivě taky skupinu Domain Controllers
- descriptor si zašlu na službu Key Distribution Service, která mi to digitálně podepíše svým soukromým klíčem (private key)
- vezmu podepsaný descriptor a nechám si veřejným klíčem (public key) služby KDS zašifrovat svoje tajná data
- tahle zašifrovaná tajná data si ani já sám nepřečtu. Uložím si to ale dohromady s tím descriptorem, který je digitálně podepsaný KDS službou
- uložení je buď právě v AD LDAPu, nebo například v PFX souboru
- když ta tajná data potřebuju na něco použít
- tak vezmu podepsaný descriptor, kterému KDSSVC služba sama věří, protože si ho sama podepsala
- a pošlu jí ta zašifrovaná tajná data spolu s tím podepsaným descriptorem (unprotect secret)
- a ono mi to vrátí ta tajná data v čisté formě. Tedy samozřejmě jen v případě, že ten kdo volá to KDS API, má ve svém access token správné skupiny (nebo přesněji řečeno SIDy)
Z toho by mělo být vidět, že tajná data si uchováváte sami, ale jediný, kdo vám je může zpřístupnit je služba Key Distribution Service. A ta služba k tomu kontroluje přístupová oprávnění a vaše členství ve skupinách na základě security descriptoru, který si mohla jen ona sama vygenerovat. Navíc se tajná data mohou povalovat úplně libovolně kdekoliv.
Všechny přenosy jsou samozřejmě normálně šifrované RPC šifrováním (tedy klíče získané z Kerberos, nebo NTLM ověření). Pokud je žadatelem o klíče rovnou operační systém řadiče domény (DC, domain controller), tak dokonce ani služba KdsSvc nemusí vůbec běžet.
Řekl bych, že by tedy už mělo být vidět, jak to funguje pro DNSSEC, failover cluster a PFX soubory, ne? Pořád ale zůstává hodně otázek ohledně group managed service account (gMSA). Jaktože ten jejich descriptor obsahuje Domain Controllers? A co tam dělá ten constructed (computed) atribut? A kdo mění heslo toho účtu? A jak? To si ale milé děti něcháme na příště, protože tohle už je opravdu hooodně dlouhé a navíc se musím jít věnovat dětem.
Ještě bych dodal, že pokud operace (un)protect key, nebo (un)protect secret, selže na nějakém počítači (tam, kde třeba pracujete s PFX souborem), tak to uvidíte v logu přímo na tomto počítači. Například:
Log: Application and Service Logs/Microsoft/Windows/Crypto-NCrypt/Operational
Event Id: 5
Event Type: Error
Event Source: Crypto-NCrypt
Message:
Protect Key operation failed.
Protector name: SID
Recipient attributes: S-1-5-21-domain-516 (domain\Domain Controllers for DC=DomainDnsZones,...)
Recipient attributes: S-1-5-9 (builtin\Enteprise Domain Controllers for DC=ForestDnsZones,...)
Flags: 0x40
Return code: 0x800706D9 = 1753 (EPT_S_NOT_REGISTERED: There are no more endpoints available from the endpoint mapper)
Log: Application and Service Logs/Microsoft/Windows/Crypto-NCrypt/Operational
Event Id: 7
Event Type: Error
Event Source: Crypto-NCrypt
Message:
Protect Secret operation failed.
Flags: 0x40
Return code: 0x80090034
Log: Application and Service Logs/Microsoft/Windows/Crypto-NCrypt/Operational
Event Id: 6
Event Type: Error
Event Source: Crypto-NCrypt
Message:
Unprotect Key operation failed.
Protector name: SID
Recipient type: Symmetric Key Encryption
Flags: 0x0
Return code: 0x800706D9 = 1753 (EPT_S_NOT_REGISTERED: There are no more endpoints available from the endpoint mapper)
Log: Application and Service Logs/Microsoft/Windows/Crypto-NCrypt/Operational
Event Id: 8
Event Type: Error
Event Source: Crypto-NCrypt
Message:
Unprotect Secret operation failed.
Flags: 0x0
Return code: 0x8009002C (NTE_DECRYPTION_FAILURE: The specified data could not be decrypted)
A ještě jedna poslední otázečka. Pokud mám více DC a přitom nejsou všechny verze Windows 2012, jak to funguje? Ona služba netlogon a její funkce DC locator má na novějších systémech schopnost vyhledat jen řadiče domény určité důležité verze. Můžete to zkusit sami pomocí nltest: (DS_6 je Windows 2008 a novější, DS_8 je Windows 2012 a novější a DS_9 je Windows 2012 R2 a novější):
nltest /dsgetDC:gopas /ds_9
A všechno nej do nového roku!