Contents of this directory is archived and no longer updated.

Posts on this page:

Когда пользователь начинает работать с PowerShell, то со временем перед ним возникает вопрос — какой редактор (вернее сказать, среду разработки) выбрать? Решений уже достаточно много, чтобы было из чего выбирать:

  • PowerShell ISE
  • PowerGUI
  • PrimalScript
  • PowerShellPlus

в большинстве случаев выбор делают между первыми двумя продуктами. Иногда споры об этом переходят в разряд религиозных войн. Истинные фанаты PowerShell выбирают ISE. В принципе, как просто редактор он вполне неплох, т.к. уже есть в коробке (начиная с первых CTP версий PowerShell V2) и для работы с ним никаких телодвижений делать не надо. Однако с ним есть ряд трудностей:

  • IntelliSense

В ISE отсутствует IntelliSense (автозавершение команд и свойств/методов объекта). А это весьма необходимая функция в среде разработки. Мне кажется, что это поняли уже все, кроме разработчиков PowerShell ISE. Вот как это может выглядеть:

PowerGUI IntelliSense support

  • Подсказки (ToolTips)

При наведении курсора на команду, не отображаются подсказки (Tooltips). В PowerGUI это выглядит действительно классно, точь-в-точь как в Visual Studio:

PowerGUI ToolTips

Причём, на этой картинке можно нажимать на стрелочки вверх/вниз для просмотра типов данных, которые принимаются в качестве аргумента. При наведении на переменную PowerGUI показывает даже тип и содержимое переменной (в разумных пределах).

  • Multiple runspaces

В ISE включена поддержка одноврменного редактирования нескольких скриптов (за счёт табов). Однако, все табы выполняются в одном runspace, что часто приводит к негативным последствиям, когда в двух разных табах используются одинаковые имена переменных. В связи с этим, данные из определённой переменной одного таба будут мигировать во второй таб, если эта переменная ещё не определена. Это может привести к неожиданным результатам работы скрипта.

  • Кодировка сохраняемых файлов

ISE по умолчанию сохраняет файлы в Big Endian кодировке. Вроде бы ничего криминального, но... Set-Authenticodesignature не умеет подписывать скрипты в Big Endian кодировке! Поэтому вы не сможете подписать штатными средствами ни один скрипт, который был сохранён в ISE! Для этого нужно прибегать к грязным хакам. Т.е. использовать такую строку, которая переопределит кодировку, в которой скрипт будет сохранён:

$psISE.CurrentFile.Save([Text.Encoding]::UTF8)
  • Исполнение сохранённых скриптов и Execution Policy

Вы можете в нём исполнять свой сценарий до тех пор, пока не сохраните его в файл. А вот когда вы редактируете уже сохранённый скрипт, то получаете бонус в виде того, что скрипт не будет исполняться внутри ISE, если у вас политика исполнения скриптов выставлена в AllSigned. ISE об этом честно предупреждает:

The script you are about to run will be saved 
Т.е. он сохраняет файл и пытается его запустить. В PowerGUI сделано куда более гуманно. Из основного редактора код условно копируется и вставляется в консоль PowerShell. Т.е. вы можете спокойно редактировать и отлаживать свой скрипт и только когда он будет готов к работе — подписывать скрипт. В случае с ISE вам придётся либо после каждого изменения сохранять и переподписывать скрипт (а это дико неудобно), либо выделять весь код и выбирать Run Selection. А это тоже не очень удобно. Плюс, сохранение скрипта перед исполнением ведёт к другой проблеме. Вы не сможете отменить изменения на более раннее состояние.

  • Поддержка профиля $Profile

В ISE вы не можете использовать свой профиль (который в консоли содержится в переменной $Profile), а только поддерживать дополнительный профиль, который находится в той же папке, что и основной, но под именем Microsoft.PowerShellISE_profile.ps1

  • Отслеживание изменений в файле

ISE не поддерживает проверку файла на изменения, хотя это должно быть удобно. Я часто редактирую свои файлы дома на нотебуке и на работе. Папка со скриптами синхронизируется между домом и работой через Live Sync. Я достаточно редко закрываю редактор, поэтому вечером сохраняю файл (который уже открыт в редакторе на работе) и всё. Утром, придя на работу я могу без переоткрытия файла могу продолжать его редактировать. PowerGUI просто сообщит, что файл был изменён и сам предложит загрузить последнюю сохранённую версию. С ISE придётся вручную переоткрывать файл.

  • About

Я не могу вспомнить программ, которые бы имели меню Help, но внутри не имели подменю About. но это просто мелочи уже, которые не влияют на удобство разработки скриптов.


Updated 04.10.2009

Если подвести это всё в табличку, то получится примерно так:

  PowerShell ISE PowerGUI PowerShell Plus
Built-In :yes: :no: :no:
Is free :yes: :yes: :no:
Fast start :no: :no: :no:
Powershell Support 100% <100% <100%
External PowerShell window :yes: :yes: :yes:
Remote PowerShell tab :yes: :no: :no:
IntelliSense :no: :yes: :yes:
Multiple Runspaces :yes: :yes: :no:
ToolTips :no: :yes: :yes:
Syntax highlighting :yes: :yes: :yes:
Error syntax highlighting :no: :yes: :yes:
Error autocorrection :no: :no: :yes:
Changed lines highlighting :no: :yes: :yes:
Outline support :no: :yes: :yes:
Support for signing :no: :yes: :yes:
Can sign within IDE :no: :no: :yes:
Run signed scripts in external window :yes: :no: :yes:
Readable command help :yes: :yes: :yes:
Configurable editor panes :yes: :yes: :yes:
Variable pane :no: :yes: :yes:
PS $Profile support :no: :yes: :yes:
BreakPoints :yes: :yes: :yes:
Code templates :no: :yes: :yes:
Print from editor :no: :yes: :yes:
Script autosave :no: :yes: :yes:

Примечание: последнее изменение таблицы 16.03.2010

Вобщем, я обозначил те вещи, которые я хотел бы видеть в хорошем редакторе. И значительное большинство моих хотелок уже есть в PowerGUI. О достоинствах PowerGUI можно говорить сколько угодно, но не буду смущать Диму Сотникова, поэтому скажу, что их продукт очень крутой. Но, в то же время, есть к чему стремиться. :-)

Однако, хочу ещё раз напомнить, что PowerGUI никогда не закроет первую строчку в таблице, что для религиозных фанатиков будет самым главным преимуществом и, который, затмит остальные недостатки ISE. Но мой выбор в этом вопросе достаточно очевиден.

После небольшого перерыва продолжаю допиливать свой вариант FCIV на PowerShell. И радостно могу сообщить, что уже есть версия 1.0, т.е. полностью отвечающая нашим требованиям. Что изменилось в новой версии?

  • Основная команда переименована с Get-PsFCIV в Start-PsFCIV;
  • Включена предварительная проверка файлов на блокировку;
  • В связи с предыдущим пунктом, к  параметру Show добавлен аргумент – Locked. В это свойство помещаются заблокированные файлы (а для них нельзя подсчитать хеш);
  • Включена проверка пути. Если путь к исходной папке не является путём файловой системы, то скрипт будет генерировать ошибку;
  • Исправлена ошибка невозврата на исходный путь, если в процессе работы произошла фатальная ошибка;
  • Параметр Show теперь выводит файлы из указанных категорий в красивое графическое окошко с использованием Out-GridView. Однако, следует учесть, что использование Out-GridView требует, чтобы был установлен .NET Framework 3.5 SP1.
  • Добавлен режим Quiet, который ничего не выводит на экран, а только генерирует коды возврата (LastExitCode). Коды возврата обновлены.
  • Пофиксены сообщения режимов Verbose и Debug.
  • Исправлены мелкие неточности в коде и произведена небольшая оптимизация кода.

А теперь и on-line справка по всем параметрам по просьбе трудящихся.

  • Path <String> — путь к папке, файлы которой следует посчитать или проверить. Допускаются относительные пути. Данный параметр обязателен.
  • XML <String> — путь к XML файлу, который содержит сведения о файлах. Если указанный файл не существует, то после пересчёта файлов по этому пути будет создан новый файл БД со сведениями о файлах. Параметр обязателен.
  • Include <String> — опциональный параметр в котором вы можете указать только конкретный файл из папки. В таком случае будет проверена не вся папка, а только указанный файл. В настоящее время параметр не поддерживает подстановочные знаки (wildcard), типа '*.ext' из-за обеспечения поддержки файлов с метасимволами (например, в имени содержатся квадратные скобки).
  • Action <String> — опциональный параметр, который указывает на действие над файлами, у которых не совпадают хеши или сведения о дате изменения и размере файла. Может принимать значение Rename или Delete. В первом случае к проблемным файлам добавляется расширение .BAD, а во втором файл просто удаляется.
  • Show <String[]> — опциональный параметр, в котором указываются категории файлов для дальнейшего анализа. В зависимости от результата проверки каждый файл (его имя) помещается в ту или иную категорию. Требует установленного .Net Framework 3.5 SP1. Может принимать один или несколько аргументов из списка:
    • Bad — содержит имена всех файлов, у которых обнаружен несовпадающий хеш или не совпадает дата/время изменеия и/или размер файла;
    • Locked — в эту категорию помещаются файлы хеш которых проверить не удалось по причине блокировки файла в монопольном режиме каким-то приложением;
    • Missed — содержит имена файлов, для которых есть запись в XML файле БД, но самого файла уже не существует (по любым причинам);
    • New — в эту категорию попадают только имена новых файлов, для которых соответствующей записи ещё нет в XML файле. Новые файлы добавляются только в режиме Rebuild или когда файл БД создаётся с нуля.
    • Ok — сюда попадают файлы с успешным статусом проверки, т.е. хеш, дата/время изменения и размер файла совпадают со значениями в XML файле;
    • Total — содержит имена всех обработанных файлов вне зависимости от результата проверки;
    • Unknown — содержит имена файлов, для которых нельзя сопоставить хеш. Такая ситуация возможна, если в параметрах функции указан только хеш SHA1, но для файла в БД записан только MD5 хеш и наоборот.
  • Recurse <Switch> — ключ, который включает проверку файлов не только в указанной папке, но и во всех вложенных папках.
  • Rebuild <Swtich> — ключ, который задаёт особый режим работы скрипта — «освежение». Если этот ключ указан, то производится сверка файлов из БД с реальными файлами. Если файл более не существует, то соответствующая запись для него удаляется из БД. После чего целевая папка (и подпапки при указанном ключе –Recurse) проверяется на наличие новых файлов. Для каждого нового файла добавляется соответствующая запись в XML файл.
  • SHA1 <Switch> — задаёт алгоритм хеширования, который будет использоваться для подсчёта новых файлов и/или для проверки уже существующих записей в XML файле.
  • MD5 <Switch> — задаёт алгоритм хеширования, который будет использоваться для подсчёта новых файлов и/или для проверки уже существующих записей в XML файле.
  • Quiet <Switch> — включает несопровождаемый режим работы скрипта. Если ключ указан, то итоговая статистическая информация не выводится на экран, а в зависимости от результата проверки генерируется код возврата (LastExitCode). Код возврата может принимать одно из следующих значений:
    • 0 — в процессе работы скрипта все файлы были успешно проверены и их хеш, дата/время изменения и размер соответствуют записям в БД. Так же, данный код возврата будет сгенерирован, если создавался новый файл БД и все файлы были успешно в него добавлены;
    • 1 — в процессе проверки были обнаружены файлы с несовпадающим хешем и/или датой/временем и размером;
    • 2 — в процессе проверки было обнаружено, что для записи в БД нет соответствующего файла;
    • 3 — в процессе проверки были обнаружены файлы, для которых не удалось сопоставить алгоритм хеширования с хранимым в БД алгоритмом хеширования для файла. Такая ситуация возможна, если в параметрах функции указан только хеш SHA1, но для файла в БД записан только MD5 хеш и наоборот;
    • 4 — в процессе работы скрипта для некоторых файлов не удалось подсчитать хеш по причине блокировки файла в монопольном режиме другим приложением;
    • 5 — скрипт выполнялся в режиме Rebuild (освежения файла БД)
  • Verbose <Switch> — включает отображение дополнительной информации о ходе проверки файлов.
  • Debug <Switch> — включает отображение отладочной информации о ходе работы скрипта.

Несколько примеров использования:

Start-PsFCIV C:\Files db.xml -SHA1 -Recurse -Show Bad, Missed

будет проверена папка C:\Files и все вложенные папки. Файл db.xml должен быть размещён непосредственно в этой папке. Если файл не существует, то будет создан с нуля. После проверки будет показано графическое окно с именами файлов, которые попали в категорию Bad и Missed. Для каждой категории будет отдельное графическое окно.

Start-PsFCIV C:\Files db.xml -SHA1 -MD5 -Include data.dat

будет проверен только файл data.dat в папке C:\Files с использованием SHA1 алгоритмом хешиования. Если для файла в БД записан только MD5 хеш, то проверка будет произведена с использованием MD5. Если файл БД (db.xml) не существует, то создастся новый файл БД со сведениями о файле data.dat. Файл будет подсчитан с использованием как SHA1, так и MD5.

Start-PsFCIV C:\Files db.xml -SHA1 -MD5 -Rebuild

будет произведено освежение файла БД для папки C:\Files. Все записи, для которых соответствующего файла не обнаружено, будут удалены. Если в папке есть файлы, для которых нет соответствующей записи, то они будут обсчитаны с использованием алгоритмов SHA1 и MD5 и будут добвлены в XML файл. Файл db.xml должен существовать, иначе скрипт вернёт фатальную ошибку.

Start-PsFCIV C:\Files db.xml -SHA1 -Quiet

Папка C:\Files будет проверена в несопровождаемом режиме с использованием алгоритма SHA1. По умолчанию никакой информации на экране не будет. После окончания работы, в зависимости от результатов проверки, скрипт сгенерирует соответствующий код возврата (0-5).

И, собственно, сам скрипт:

И как обычно, любые замечания, комментарии постить в каменты.

Update: этот пост периодически обновляется.


Вот и пришло время сделать сводный пост по своим исследованиям Software Restriction Policies. Здесь я опубликую ссылки на предыдущие материалы, посвящённые этой действительно интересной технологии. К сожалению это скорее всего будет означать завершение срывов покровов в этом направлении. Безусловно, технологии не стоят на месте, а постоянно развиваются, поэтому очень долго топтаться на одном месте не стоит. Но это совсем не означает, что SRP стал реликвией, музейным экспонатом и просто утилем. SRP до сих пор имеет и какое-то время будет иметь важное значение в обеспечении безопасности ОС Windows, поскольку теперь политики SRP поставляются во все домашние редакции Windows 7. А так же будет неотъемлемой частью обеспечения безопасности уже активно используемых систем начиная с Windows XP.

И, собственно, сам список.

Опубликованная в журнале «Системный администратор» статья даст представление о том, что такое SRP, поведает о ключевых особенностях этих политик и может выступать в качестве теоретической базы для работы с SRP.

Первая часть исправлений к журнальной статье, в которой рассказывается про особенности использования прямых «/» и обратных «\» слешей в правилах пути, а так же про обход политик через системные папки, которые разрешены пользователям для записи.

В этой части рассказаны методы обхода SRP на примере запуска CHM файлов и потенциальной возможности запуска некоторого кода с использованием файлов с расширением SCF. Плюс даны некоторые рекомендации по организации правил для типовой рабочей станции и косметические настройки обработки групповых политик в отношении SRP.

Очередной обзор нескольких способов обхода политик SRP путём подмены системных переменных окружения, использованием в обработке расширений LNK и подстановкой нелегитимных доверенных издателей (цифровых подписей). Так же приведён потенциальный полувандалистский метод атаки на SRP путём генерации зашедуленного задания в ожидании, когда политика будет отключена в профилактических целях.

В этом посте детально рассказано о непростом порядке сортировки и применения множества правил SRP. Используя этот материал вы научитесь разрешать конфликты в правилах и упростит планирование правил SRP.

И ещё один метод обхода политик SRP через шорткаты и обнаружение второй достаточно серьёзной уязвимости SRP, которую закрыть достаточно сложно.

содержит официальное заявления сотрудника техподдежки Microsoft — Rahul Denkanikota. В результате двухмесячного общения с техподдержкой мне лично была предложена замена для mshta.exe, которая уже лишена недостатка оригинального файла. Однако, данное решение не планируется выпускать в массы по причине очень большой специфики. В остальных же случаях, если это возможно, следует полностью отказаться от mshta.exe и заблокировать его на уровне правил SRP.

В этом посте опубликовано решение, которое позволяет защитить SRP от подстановки ложных сертификатов цифровых подписей. В целом, с некоторыми оговорками, после данного поста репутация SRP вновь восстановлена до уровня «надёжно».

Краткая статья, содержащая сравнение возможностей SRP и его последователя, AppLocker.

В этой части рассказывается о проблемах и их решении при внедрении SRP в 64-разрядных ситемах, терминальных серверах и небольшой рассказ об отличиях правил SRP в Windows Vista и более новых систем по сравнению с pre-Vista системами (Windows XP/Server 2003).

Коллекторский пост, содержащий ссылки на статьи в knowledge base (KB), связанные с теми или иными проблемами работы с SRP.

Вот и всё… :pop:

Примечание: данный материал публикуется как обязательный для знания IT-специалистами, которые занимаются или только собираются заниматься темой PKI (Public Key Infrastructure).

Введение

На самом деле эта тема тесно переплетается с фундаментальными основами PKI, как доверие сертификатов, защита от подделки цифровых подписей сертификатов, отзыв сертификатов и т.д. Иными словами, сама модель PKI лежит на Certificate Chaining Engine (механизм построения цепочек сертификатов). Миллионы людей в мире видят результат работы этого механизма ежедневно, но не знают, как он работает. Им это, в принципе, и не надо, а вот IT-специалистам по PKI это знать просто необходимо.

Одной из основ PKI является модель доверия центрам сертификации (Certification Authority или просто CA). Прежде чем мы начнём доверять сертификату мы должны явно доверять корневому сертификату CA и так же явно или косвенно (по правилу одностороннего транзитивного доверия) доверять всем промежуточным CA в цепочке. Корневые сертификаты устанавливаются в систему вручную путём добавляения сертификата CA в секцию Trusted Root CAs. Если корневой сертификат CA есть в этом списке, то мы доверяем всем сертификатам, которые выдал этот CA и любые подчинённые CA (Intermediate CA).

В качестве наиболее доступного и понятного примера можно рассмотреть SSL веб-сайт. Если мы зайдём на https://www.dreamspark.com, то мы увидим что с SSL сертификатом этого сайта всё в порядке. Если же мы зайдём на https://cert.startcom.org, то мы наоборот увидим грозное предупреждение, что с SSL сертификатом этого сайта что-то не так. Это как раз и есть результат работы Chaining Engine. А вот что он сделал на самом деле — вот об этом мы сейчас и поговорим.

Постройка цепочки сертификатов

Давайте сначала посмотрим на путь сертификатов (цепочки сертификатов) обоих веб-сайтов:

 Valid certification path   Invalid certification path with untrusted root

В первом случае цепочка сертификатов заканчивается на сертификате VeriSign, которому мы доверяем явно. Вы можете убедиться в этом нажав кнопку View Certificate, чтобы посмотреть его внутренности и найти этот же сертификат в оснастке certmgr.msc –> Trusted Root CAs. Однако, вы видите, что не корневой CA выдал сертификат сайту, а подчинённый (Intermediate CA). Это доказывает то, что если мы доверяем корню, то и явно или косвенно доверяем всем сертификатам этого CA или любым его прямым или косвенным промежуточным CA. Если говорить простым языком, то в сертификатах используется одностороннее транзитивное доверие сертификатам CA. Чуть позже будет рассказано как строится эта цепочка. Во втором случае мы видим, что корневой сертификат CA не находится у нас в Trusted Root CAs и, следовательно, мы не доверяем ни одному сертификату, который издал этот CA или любой другой его подчинённый CA. И, так же как и в первом случае, сертификат самому веб-сайту выдал подчинённый CA. На самом деле этот момент является одной из наиболее частых ошибок системных администраторов, которые организовывают доступ к ресурсам с использованием цифровых сертификатов.

Но нас теперь интересует другой вопрос — а откуда же взялись все эти сертификаты в цепочке? Chaining engine как правило использует только 3 метода построения цепочки:

  • по полю AIA (Authority Information Access) каждого сертификата
  • с использованием файла цепочки сертификатов в формате pkcs7
  • поиск подходящих сертификатов в локальном хранилище (с использованием exact, key, name matches, о которых будет рассказно ниже)

Примечание: в сертификате любое поле содержащее слово Authority будет означать какие-то сведения о сертификате вышестоящего CA. Например, Authority Key Identifier — комбинация серийного номера, поля Subject или хеша открытого ключа вышестоящего CA. А любое поле содержащее слово Subject — означает то же самое, но применительно к конкретно этому сертификату.

Давайте посмотрим поле AIA первого сертификата:

[1]Authority Info Access
     Access Method=Certification Authority Issuer (1.3.6.1.5.5.7.48.2)
     Alternative Name:
          URL=
http://www.microsoft.com/pki/mscorp/Microsoft%20Secure%20Server%20Authority(5).crt

В этом поле содержится ссылка на сертификат того CA, который непосредственно издал и подписал этот сертификат. Если нажать по этой ссылке, то вы скачаете сертификат центра сертификации Microsoft Secure Server Authority. В этом сертификате тоже будет поле AIA, по ссылке из которого скачается сертификат вышестоящего CA — Microsoft Internet Authority. И так проверка проводится далее до тех пор, пока цепочка не оборвётся или не закончится каким-либо корневым CA (корневой CA характеризуется самоподписанным сертификатом, т.е. сертификат выдан самому себе). Если вы посмотрите сертификат Microsoft Internet Authority, то вы в нём не обнаружите поля AIA. И вот здесь мы сталкиваемся со вторым методом добычи сертификатов в цепочке – файл сертификатов формата pkcs7.

Бывают случаи, когда цепочка сертификатов не может быть построена и она обрывается на пути. Типичный пример такого обрыва (когда цепочка не может быть построена до корня с использованием любого вышеуказанного метода) можно посмотреть на сайте БиЛайна: https://trust.beeline.ru

 Invalid certificate chain. Root certificate s unreachable

если посмотреть поле AIA этого сертификата, то мы увидим там 2 пути до CA, который издал этот сертификат. Но оба эти пути нерабочие совсем (кстати говоря, пути в CDP там тоже нерабочие. Причём, во всех сертификатах! Вот такой он БиЛайн :-) ). Но цепочка сертификатов в этом случае всё равно построилась за счёт сертификатов в pkcs7 формате. Хотя корневой сертификат в этом pkcs7 просто отсутствует, поэтому мы даже не можем собрать корневой сертификат. Неработающие CDP/AIA — ещё одна из наиболее частых ошибок реализации инфраструктуры PKI, в результате которой по сути PKI является неработоспособной.

Оффтоп: если на этой странице нажать Продолжить, то на новой странице будет ссылка на корневой сертификат, а так же на CRL. CRL БиЛайна доставил очень сильно. Вы посмотрите срок годности этого CRL :-)

Проверка соответствия сертификатов внутри построенной цепочки

Однако, это только половина дела. Мы просто построили цепочку сертификатов, но не более того. Поскольку сертификаты могут быть скачаны в pkcs7 формате, а по ссылкам AIA просто подменить сертификаты, chaining engine делает полнуюю проверку доверия каждого сертификата в цепочке, чтобы исключить возможность подмены сертификатов, а так же достраивает цепочку (если этого не удалось сделать с помощью AIA и pkcs7 используя локальное хранилище сертификатов). Соответствие сертификатов внутри цепочки может происходить по нескольким правилам (в порядке приоритета):

  • Exact Match
  • Key Match
  • Name MAtch

Для этого chaining engine использует следующие поля сертификатов:

  • Authority Key Identfier (AKI) — может содержать комбинацию поля Subject и Serial Number сертификата вышестоящего CA или хеш открытого ключа вышестоящего CA (но бывает, что это поле совсем отсутствует).
  • Issuer – данное поле используется только если AKI отсутствует в сертификате и это поле должно быть эквивалентно полю Subject вышестоящего CA. По этому полю определяется имя CA, котороый издал этот сертификат.
  • Subject в сертификате вышестоящего CA. Данное поле должно быть эквивалентно полю Issuer в издаваемых сертификатах.
  • Serial Number сертификата вышестоящего CA.
  • Subject Key Identifier (SKI) — может содержать комбинацию поля Subject и Serial Number текущего сертификата или хеш открытого ключа текущего сертификата.

Exact match

Данный метод определения правильности построения цепочки является наиболее точным и такая цепочка почти никогда не будет заканчиваться более чем одним корневым сертификатом, поскольку требует совпадения 2-х полей вышестоящего сертификата – Subject и серийного номера с полем AKI проверяемого сертификата. Давайте посмотрим пример такой проверки в сертификате сайта https://cert.startcom.org. Поле AKI содержит следующую информацию:

KeyID=a1 e1 9e 45 25 79 4d 06 d9 02 17 92 82 d5 30 89 72 25 14 a0
Certificate Issuer:
     Directory Address:
          CN=StartCom Certification Authority
          OU=Secure Digital Certificate Signing
          O=StartCom Ltd.
          C=IL
Certificate SerialNumber=17

Поле KeyID не используется. Здесь мы видим сведения о поле Subject и серийный номер вышестоящего CA. Если посмотреть сертификат этого CA, то его серийный номер и поле Subject будут идентичными тем, которые записаны в поле AKI издаваемых ими сертификатов. Используя эти данные chaining engine может найти нужный сертификат в локальном хранилище (если такой сертификат там есть), для восполнения недостающих звеньев цепочки. Если же будет обнаружено хоть одно несоответствие между этими полями, то цепочка мгновенно обрывается и любому сертификату в этой цепочке (начиная от сертификата с несоответствующими полями и вниз до конечного сертификата выданного потребителю) будет отказано в доверии.

Key Match

Это наиболее распространённый тип проверки цепочки, т.к. зачастую поле AKI у сертификатов содержит только KeyID, который является лишь хешом открытого ключа вышестоящего CA. Например сертификат с https://www.dreamspark.com:

KeyID=14 55 c4 39 e0 3d 2e d1 55 2e 48 96 b0 d8 7e 14 22 06 93 bc

Этот хеш должен быть идентичным хешу, который записан в поле Subject Key Identifier вышестоящего CA. В этом вы можете убедиться просмотрев сертификат CA, который выдал сертификат для dreamspark.com. В случае несоответствия этого поля, любому сертификату вниз по цепочке будет отказано.

Заметка: при этом, возможна достаточно интересная ситуация, когда цепочка может заканчиваться несколькими корнями. Это может происходить если корневой сертификат CA был обновлён с использованием текущей пары открытого и закрытого ключа. Поскольку KeyID — всего лишь хеш открытого ключа, то при смене корневого сертификата CA, хеш не изменится и, следовательно, chaining engine может рандомно строить цепочку до старого или до нового корневого сертификата CA.

Name match

Но поле AKI не обязательно должно присутствовать в сертификате. Его может не быть совсем и тогда остаётся только один способ проверки целостности цепочки — сравнение поля Issuer текущего сертификата и поля Subject вышестоящего сертификата. Это самый крайний и наименее надёжный (хотя это достаточно относительно) метод проверки цепочки. Так же, как и предыдущий пример, данный метод может заканчиваться несколькими корневыми сертификатами, если сертификат CA был обновлён с использованием текущей пары открытого и закрытого ключей. Но этого не произойдёт, если при обновлении сертификата CA будут использоваться новая пара ключей. Хоть хеши и серийные номера издающих CA не проверяются, то подделка сертификатов в вашем случае закончится провалом. А об этом читайте заключительный раздел.

Не забываем про подписи

На самом деле может показаться, что обмануть chaining engine достаточно легко — надо лишь подсунуть нужные поддельные сертификаты. Но в действительности это не так. Помимо всего прочего следует помнить, что каждый сертификат подписан цифровой подписью издающего CA. Если вы ещё не знаете, что такое цифровая подпись, то пора бы и узнать. Когда CA составляет сертификат, то он высчитывает конечный хеш (с использованием алгоритма указанного в поле Signature algorithm) этого сертификата и шифрует его своим закрытым ключом и пристыковывает подпись к сертификату. При проверке сертификата chaining engine удаляет цифровую подпись из сертификата и подсчитывает сам хеш файла сертификата. Далее берёт открытый ключ у издающего CA и сравнивает полученный хеш с тем, что содержится в подписи. Следовательно, если вам удастся обмануть все 3 метода проверки цепочки путём подмены сертификатов, то вы сломаетесь на проверке цифровой подписи, т.к. здесь уже задействуется закрытый ключ легального CA. Вот как это может выглядеть:

Altered certificate certification path Altered certificate General tab

На картинке слева вы видите, что chaining engine построил цепочку до доверенного корня, поскольку мой сертификат содержал нужные поля для работы метода Name match. Но сертификат был выдан не тем CA, который виден в цепочке, а поддельным CA. Хоть мой поддельный CA внешне не отличим от легитимного CA, но у него нету самого важного — правильного закрытого ключа, чтобы подписать сертификат. Ведь при проверке подписи используется открытый ключ легитимного CA и, следовательно, подпись не может быть проверена.

Написал очень много страшных букв даже без надежды, что кто-то с первого раза поймёт о чём тут шёл разговор. Но поверьте, это достаточно полезное знание, чтобы уметь отыскивать и разрешать проблемы с построением цепочек сертификатов.

Представлю на обозрение пробный скрипт по управлению сертификатами в хранилище Certificate Store — CertMgmtPack.ps1, который (как я надеюсь) может найти применение на серверах Windows Server 2008 R2 Server Core и реализован на основе наших недавних исследований:

Версия пока что 0.47 (т.к. предстоит добавить ещё разного функционала и допилить существующий). Пока что мне удалось реализовать функционал импорта сертификатов из файлов в store и экспорт из store в файлы сертификатов.

Примечание: скрипт работает только в PowerShell V2. В каждую функцию вложена справка, которую вы можете прочитать набрав Get-Help Import/Export-Certiifcate.

После подключения скрипта (используя dot-sourcing) у вас будут доступны 2 функции:

  • Export-Certificate
  • Import-Certificate

И пару слов о том, как их использовать.

Import-Certificate

содержит следующие параметры:

  • Path <String> — путь к файлу сертификата, который может иметь следующий набор расширений: CER, DER, PFX, P7B, SST. Распознавание типов сертификатов осуществляется по расширению файла. Данная функция может принимать параметр пути из конвейера следующим путём:
    dir *.cer | Import-Certificate
    
    Параметр обязательный.
  • Password <SecureString> — пароль для PFX файла. Пароль не требуется для остальных типов файлов. Однако, хочу предупредить, что пароли не принимаются в открытом виде, а должны передаватьсякак SecureString. Это можно реализовать различными способами, например, вот так:
    Read-Host "Enter password for PFX file" –AsSecureString
  • Storage <String> — указывает контекст импорта сертификата, т.е. это будет хранилище текущего пользователя (по умолчанию) или в хранилище компьютера (требуются права локального администратора). Может принимать значения User или Computer. Если параметр не указан, то берётся значение по умолчанию — User.
  • Container <String> — указывает контейнер размещения сертификата. Это может быть один из: AuthRoot, CA, Disallowed, My (по умолчанию), REQUEST, Root, SmartCardRoot, Trust, TrustedPeople, TrustedPublisher, UserDS. Расшифровка контейнеров (сопоставление названиям в оснастке CertMgr.msc) приведена внутри скрипта в хелпе функции. Если параметр не указан, то применяется параметр по умолчанию — My.
  • Exportable <Switch> — применяется только для импорта PFX файлов. Данный ключ помечает импортируемый сертификат как экспортируемый. Это означает, что вы после процедуры импорта сможете снова экспортировать сертификат с закрытым ключом. Эсли ключ Exportable не указан, то закрытый ключ сертификата не помечается как экспортируемый и при экспорте у вас не будет возможности экспортировать закрытый ключ данного сертификата.
  • StrongProtection <Switch> — применяется только для импорта PFX файлов. Данный ключ включает режим усиленной защиты закрытого ключа PFX файла. Это означает, что для каждой попытки использования закрытого ключа от этого сертификата потребуется ручной ввод пароля. Данный ключ нельзя использовать, если Storage указан как Computer, поскольку компьютерные сертификаты не поддерживают такой режим. Это связано с тем, что компьютерные сертификаты используются в контексте учётной записи LocalSystem и lsass.exe не предоставляет пользователю UI для ввода пароля. В любом случае, если вы попробуете это сделать, скрипт выдаст соответствующую ошибку и импорт произведён не будет.

И пару примеров, как использовать функцию:

$pass = Read-Host "Enter password for PFX" –AsSecureString
Import-Certificate mycert.pfx -Password $pass -Exportable

импортирует файл mycert.pfx в контейнер Personal хранилища текущего пользователя и пометит ключ как экспортируемый.

Import-Certificate mycert.pfx -Password $pass -StrongProtection

Импортирует файл mycert.pfx в контейнер Personal хранилища текущего пользователя, пометит ключ как неэкспортируемый и включит режим усиленной защиты закрытого ключа, что потребует ввод пароля пользователя каждый раз при его использовании.

Import-Certificate certs.p7b –Storage 'Computer' –Container 'TrustedPublisher'

Импортирует все сертификаты из файла certs.p7b в контейнер Trusted Publishers компьютерного хранилища.

Экспорт сертификатов

  • Path <String> — указывает путь к папке (не к файлу!), в которую будут экспортированы все указанные сертификаты. Парамер обязателен.
  • Type <String> — указывает тип экспортируемых сертификатов. Может принимать одно из значений: CERT, PFX, PKCS12, PKCS7, SST (Serialized Store). Параметр так же обязателен.
  • Password <SecureString> — задаёт пароль для экспортируемых PFX файлов (в качестве типа экспортируемых сертификатов указано PFX или PKCS12 и является для них обязательным). Параметр не принимает значение в виде простой строки, а только SecureString.
  • Storage <String> — указывает контекст поиска экспортируемых сертификатов, т.е. поиск будет производиться в компьютерном хранилище или хранилище текущего пользователя (по умолчанию). Может принимать значения CurrentUser или LocalMachine. Если параметр не указан, то берётся значение по умолчанию — User.
  • Container <String> — указывает контейнер размещения сертификата (или сертификатов). Это может быть один из: AuthRoot, CA, Disallowed, My (по умолчанию), REQUEST, Root, SmartCardRoot, Trust, TrustedPeople, TrustedPublisher, UserDS. Расшифровка контейнеров (сопоставление названиям в оснастке CertMgr.msc) приведена внутри скрипта в хелпе функции. Если параметр не указан, то поиск производится в контейнере по умолчанию — My.
  • Thumbprint <String> — задаёт критерий поиска сертификатов по отпечатку ключа (соответствующее поле Thumbprint сертификата). Можно указывать как полный отпечаток, так и любую его часть.
  • Subject <String> — задаёт критерий поиска сертификатов по полю Subject. Можно указывать как полный Subject, так и любую его часть.
  • Issuer <String> — задаёт критерий поиска по конкретному издателю сертификата. Можно указывать как полный CN издателя, так и любую его часть.
  • SerialNumber <String> — задаёт критерий поиска по серийному номеру сертификата. Можно указывать как точный серийный номер, так и любую его часть.
  • NotAfter <String> — задаёт критерий поиска по дате истечения сертификата. Дата задаётся в формате dd.MM.yyyy (день.месяц.год). В результате использования этого параметра будут отобраны сертификаты, которые истекут не позднее указанной даты.
  • NotBefore <String> — задаёт критерий поиска по дате начала действия сертификате. Как и в NotAfter дата указывается в формате dd.MM.yyyy и в результате использования этого параметра будут отобраны сертификаты, действие которых начинается не раньше указанной даты.
  • DeleteKey <Swtich> — используется только при экспорте сертификатов вместе с закрытыми ключами в PFX файлы. Данный ключ при успешном экспорте удаляет закрытый ключ данного сертификата из хранилища.

Я не смог провести полноценное тестирование функции экспорта, поэтому гарантировать 100% работу пока не могу. Но вы, уважаемые читатели, можете мне в этом помочь.

И несколько примеров использования:

Export-Certificate c:\certs -Type 'PKCS7'

Экспортирует все сертификаты из Current User\Personal в один PKCS7 файл с именем ExportedCertificates.p7b (это имя зашито на уровне скрипта).

Export-Certificate c:\certs -Type 'cert' -Storage 'LocalMachine' -Container 'Root' -SerialNumber '663'

Экспортирует все сертификаты из контейнера доверенных центров сертификации (Trusted Root CAs) компьютерного хранилища, у которых в серийном номере встречается последовательность 663 в CER файлы. При этом каждый сертификат будет экспортирован в индивидуальный файл с именем, которое строится по схеме: SubjectCN_Thumprint.CER, например: Thawte Premium Server CA_4F65566336DB6598581D584A596C87934D5F2AB4.cer

Export-Certificate c:\certs -Type 'PKCS12' -Password $pass -DeleteKey -Subject 'UserName'

Экспортирует все сертификаты из Current User\Personal в PFX файлы у которых в любом месте поля Subject есть UserName. При успешном экспорте закрытый ключ сертификата будет удалён из хранилища и будет содержаться только в PFX файле.

В связи с тем, что CN поля Subject может содержать недопустимые символы для имён файлов, мне скорее всего придётся искать другой метод именования экспортируемых сертификатов и чтобы они были распознаваемые. Если вы обнаружите какие-то ошибки или будут пожелания, то пишите мне в коментарии или на почту. По мере дописывания я буду выкладывать новые версии скрипта.