Я вчера в статье Certificate Trust List (CTL) в PowerShell показал основные принципы, как работать с CTL в PowerShell. Сегодня я продолжу тему и покажу, как можно вытащить доверенные корневые сертификаты из ресурсов Crypt32.dll и из интернетов. Но для начала, Crypt32.dll
Вот как они выглядят в каком-нибудь редакторе ресурсов:
Примечание: в Windows XP и Windows Server 2003 этих ресурсов не будет. Они есть только в системах начиная с Windows Vista.
Выглядит не очень презентабельно, просто они хранятся там в сериализированном виде (serialized store). Нас будет интересовать AUTHROOTS и UPDROOTS. В WinAPI есть целая вязанка функций, которые отвечают за работу с ресурсами: Resource Functions. Нас будет интересовать только следующие функции:
И вот сигнатуры функций:
$signature = @" [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern IntPtr LoadLibraryEx( String lpFileName, IntPtr hFile, UInt32 dwFlags ); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr FindResource( IntPtr hModule, int lpID, string lpType ); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern uint SizeofResource( IntPtr hModule, IntPtr hResInfo ); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr LoadResource( IntPtr hModule, IntPtr hResInfo ); [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern bool FreeLibrary( IntPtr hModule ); "@ Add-Type -MemberDefinition $signature -Namespace PKI -Name Kernel32
А дальше всё просто:
$path = $Env:SystemRoot + "\System32\crypt32.dll" # загружаем Crypt32.dll в память $hModule = [PKI.Kernel32]::LoadLibraryEx($path,[IntPtr]::Zero,0x2) # ищем ресрус AUTHROOTS под номером 1010 $hResInfo = [PKI.Kernel32]::FindResource($hModule,1010,"AUTHROOTS") # вычисляем размер ресурса для создания буфера в managed memory $size = [PKI.Kernel32]::SizeOfResource($hModule, $hResInfo) # загружаем ресурс в unmanaged memory и получаем pointer на него $resource = [PKI.Kernel32]::LoadResource($hModule, $hResInfo) # создаём буфер для ресурса $bytes = New-Object byte[] -ArgumentList $size # и маршалером копируем ресурс из неуправляемой памяти в наш буфер. # данные будут представлять собой serialized certificate store. [Runtime.InteropServices.Marshal]::Copy($resource, $bytes, 0, $size) # ход конём: создаём объект X509Certificate2Collection, который поддерживает # сериализированные хранилища SST $AUTHROOTS = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection # импортируем наши байтики в X509Certificate2Collection $AUTHROOTS.Import($bytes) # повторяем процедуру для UPDROOTS $hResInfo = [PKI.Kernel32]::FindResource($hModule,1011,"UPDROOTS") $size = [PKI.Kernel32]::SizeOfResource($hModule, $hResInfo) $resource = [PKI.Kernel32]::LoadResource($hModule, $hResInfo) $bytes = New-Object byte[] -ArgumentList $size [Runtime.InteropServices.Marshal]::Copy($resource, $bytes, 0, $size) $UPDROOTS = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection $UPDROOTS.Import($bytes) [PKI.Kernel32]::FreeLibrary($hModule)
И вот что у нас на выходе:
[↓] [vPodans] $AUTHROOTS[0..5] Thumbprint Subject ---------- ------- 879F4BEE05DF98583BE360D633E70D3FFE9871AF CN=NetLock Uzleti (Class B) Tanusitvanykiado, OU=Tanusitvanykiadok, O=NetL... E12DFB4B41D7D9C32B30514BAC1D81D8385E2D46 CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Netw... 0483ED3399AC3608058722EDBC5E4600E3BEF9D7 CN=UTN-USERFirst-Hardware, OU=http://www.usertrust.com, O=The USERTRUST Ne... 58119F0E128287EA50FDD987456F4F78DCFAD6D4 CN=UTN - DATACorp SGC, OU=http://www.usertrust.com, O=The USERTRUST Networ... D29F6C98BEFC6D986521543EE8BE56CEBC288CF3 E=certificate@trustcenter.de, OU=TC TrustCenter Class 4 CA, O=TC TrustCent... 838E30F77FDD14AA385ED145009C0E2236494FAA E=certificate@trustcenter.de, OU=TC TrustCenter Class 2 CA, O=TC TrustCent... [↓] [vPodans] $UPDROOTS[0..5] Thumbprint Subject ---------- ------- 132D0D45534B6997CDB2D5C339E25576609B5CC6 CN=VeriSign Class 3 Public Primary Certification Authority - G3, OU="(c) 1... 204285DCF7EB764195578E136BD4B7D1E98E46A5 CN=VeriSign Class 1 Public Primary Certification Authority - G3, OU="(c) 1... 801D62D07B449D5C5C035C98EA61FA443C2A58FE CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Lim... 8939576E178DF705780FCC5EC84F84F6253A4893 CN=Entrust.net Secure Server Certification Authority, OU=(c) 2000 Entrust.... 7030AABF8432A800666CCCC42A887E42B7553E2B CN=eSign Imperito Primary Root CA, OU=Public Secure Services, O=eSign Aust... C73026E325FE21916B55C4B53A56B13DCAF3D625 CN=Gatekeeper Root CA, OU=Gatekeeper PKI, O=eSign Australia [↓] [vPodans]
Я показал только по 6 первых элементов из каждого ресурса. На самом деле их там чуточку больше:
[↓] [vPodans] $AUTHROOTS.Count 87 [↓] [vPodans] $UPDROOTS.Count 165
С этим списком вы уже можете делать что хотите. Единственное, что я могу посоветовать — не пропускайте их без лишней надобности через certificate chaining engine (это включает как вызов метода Verify(), использование в X509Chain или просмотр сертификата в UI, т.к. это тоже запускает certificate chaining engine), потому что они будут устанавливаться в хранилище. А оно вам надо?
Однако, этот список не самый актуальный. Если не ошибусь, он обновляется (в самой библиотеке) с выходом сервис-пака. А список членов программы изменяется почаще (см: Windows Root Certificate Program Members). И вот пруф номер 2:
[↓] [vPodans] $UPDROOTS | ?{$_.thumbprint -eq "C060ED44CBD881BD0EF86C0BA287DDCF8167478C"} Thumbprint Subject ---------- ------- C060ED44CBD881BD0EF86C0BA287DDCF8167478C E=info@diginotar.nl, CN=DigiNotar Root CA, O=DigiNotar, C=NL [↓] [vPodans] dir cert:\CurrentUser\Disallowed\C060ED44CBD881BD0EF86C0BA287DDCF8167478C Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\Disallowed Thumbprint Subject ---------- ------- C060ED44CBD881BD0EF86C0BA287DDCF8167478C E=info@diginotar.nl, CN=DigiNotar Root CA, O=DigiNotar, C=NL [↓] [vPodans]
А, ведь, DigiNotar выпилен из программы.
На практике это происходит вот как: клиент скачивает самый свежий authrootstl.cab, списывает себе хеши и выпиливает все сертификаты из Third-Party CAs, чьи хеши не представлены в CTL. А если в CTL есть хеш нового участника, а сертификата у клиента нету? Он его должен где-то взять и заныкать до лучших времён (т.е. доставит в хранилище по первому требованию). Берёт его он примерно вот здесь: http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/<Thumbprint>.crt
Возьмём какой-нибудь сертификат (из тех, что есть в Crypt32.dll) и поштриноль:
[↓] [vPodans] $rm = Invoke-RestMethod "http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/879 F4BEE05DF98583BE360D633E70D3FFE9871AF.crt" [↓] [vPodans] [byte[]]$rm = $rm.ToCharArray() | %{[byte]$_} [↓] [vPodans] New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 (,$rm) Thumbprint Subject ---------- ------- 879F4BEE05DF98583BE360D633E70D3FFE9871AF CN=NetLock Uzleti (Class B) Tanusitvanykiado, OU=Tanusitvanykiadok, O=NetL... [↓] [vPodans]
Командлет Invoke-RestMethod появился в PowerShell 3.0 и является простым враппером для WebRequestCmdlet. Т.е. при наличии интернетов, вы можете взять authrootstl.cab и через Invoke-RestMethod или Invoke-WebRequest накачать себе сертификатов под завязку :-)
Что-то я не понял, а зачем это? Что с ними потом можно сделать? Закрытых ключей же с ними не будет?
А кто сказал, что это делается с целью извлечения ключей? Я пост написал не просто так, а потому что заметил, что народ спрашивает (особенно когда в их компаниях действует строгая политика аудита).
Comments: