Contents of this directory is archived and no longer updated.

Posts on this page:

Остальные материалы цикла:


КДПВДанная серия постов заказана и оплачена благотворительным фондом винниклОлега Крылова и всех-всех-всех.

Исходя из названия серии, мы, очевидно, будем говорить про цифровые сертификаты и аутентификацию. Для начала предлагаю классический бэкграунд аутентификации другими средствами (паролями же!).

Password-based authentication background

Почти всю свою историю человек использует аутентификацию на основе комбинации логин и пароль. Логин уникально идентфицирует пользователя, а пароль (или секретное слово) подтверждает, что я — это я, а не Вася, который выдаёт себя за меня. Но давайте посмотрим слабые места парольной аутентификации в IT:


Read more →

КДПВВ разных интернетах ходят разные толки по поводу Policy CA. В своё время я давал краткую справку о нём: Обсуждение схем иерархии Certification Authority и есть необходимость немного дополнить ту статью и показать применением выделенного Policy CA в реальном мире. Назначение Policy CA вполне понятно — разделять PKI на одну или несколько веток, которые будут различаться правилами выдачи и обслуживания сертификатов. Интернеты (и разные там специалисты) всячески рекомендуют деплоить 3-х уровневые иерархии вида:

Offline Root CA
           Offline Policy CA
                      Online Issuing CA

Это считается бест-практисом. Отдельные люди указывали мне, что совмещение ролей (Policy и Issuing) не есть хорошо по причине безопасности и всё такое. Но если говорить о бест-практисах, то их здесь нету совсем. Есть только некоторые рекомендации, по которым можно подобрать себе оптимальную иерархию. Всё остальное является следствием буйной фантазии. Давайте ещё раз пробежимся по этим моментам.

Когда применяем 1-уровневую иерархию?

Если у вас небольшая компания (скажем, человек 10-100) без особых требований к PKI, вы спокойно разворачиваете одноуровневую иерархию с Online Root CA и используете сертификаты для логона (VPN, IIS и/или применяете смарт-карты) или шифруете данные. Как пример. Хоть я в предыдущей статье весьма критически относился к такому решению, оно в реальном мире вполне себе жизнеспособно (опыт иногда меняет отношение к каким-то вопросам в ту или иную сторону). Не потому что она ВНЕЗАПНО стала безопасной, а потому что это элементарно выгодней, чем покупать отдельное железо и лицензию Windows Server, даже если посчитать все риски. Плюс, экономия на административных издержках. Т.е. это случаи, когда компрометация PKI не ведёт к краху всего бизнеса, хотя это не очень приятно.

Для сравнения можно представить, сколько администраторов не делает бакупов. Бакупы — это вообще отдельная тема и ситуация с ними катастрофическая. Вы просто не представляете сколько компаний не делают бакупы. А когда один единственный (или парочка) выходят из строя, теряя всю финансовую отчётность и вообще всё, чем занималась компания — этот фейл более реальный и более эпический.

Когда применяем 2-уровневую иерархию?

Если вы интегрируете PKI в свою сеть более тесно (вы внедряете цифровые подписи, устанавливаете VPN между сайтами, появляются удалённые SCCM/OpsMgr клиенты и т.д.), вы скорее всего будете более благоразумны и примените 2-х или 3-х уровневую иерархию. На этом этапе у вас PKI может начать делиться, потому что сферы применения PKI становятся шире. И вот здесь может появиться желание вбахать выделенный Policy CA, который опишет политику применения (CPS) сертификатов в вашей организации. С одной стороны это выглядит идеологически правильно. Но с другой стороны это не очень практично. Дело в том, что CPS можно прикрутить и к издающим CA, совместив роль Policy и Issuing CA. Об этом я уже писал в предыдущей статье.

Даже если у вас на уровне шаблонов сертификатов действуют разные политики, их вполне возможно описать в пределах одного CPS. Политики на уровне шаблонов могут быть очень разнообразные: например, чтобы получить сертификат для шифрования данных достаточно залогониться в систему. А чтобы получить логонный сертификат на смарт-карте, нужно оформить соответствующую заявку и нотариально заверить у руководителя отделом. Для получения сертификата цифровой подписи (для подписи документов), нужно в должности быть руководителем какого-то отдела. Это наиболее распространённые примеры из реальной жизни.

Учитывая, что в этих случаях у вас будет один CPS, вы можете на уровне издающего CA применить OID = All Issuance Policies (2.5.29.32.0) в CAPolicy.inf:

[PolicyStatementExtension]
Policies = SomeCPS

[SomeCPS]
URL = Some URL 
OID = 2.5.29.32.0

Т.е. CA может выдавать сертификаты с использованием любых политик выдачи и использования сертификатов, которые более конкретно определены в CPS. Так же, данный сценарий позволяет провести последующую кросс-сертификацию с другой PKI (см. Что в OID'е тебе моём?). Если CA может издавать сертификаты только по конкретным политикам, вы можете ограничить CA только ими, применив следующий шаблон для CAPolicy.inf:

[PolicyStatementExtension]
Policies = CPS1, CPS2, CPS3

[CPS1]
URL = URL1
OID = 1.3.6.1.4.1.12345.1

[CPS2]
URL = URL2
OID = 1.3.6.1.4.1.12345.2

[CPS3]
URL = URL3
OID = 1.3.6.1.4.1.12345.3

В результате, CA сможет выдавать сертификаты на основе тех шаблонов (здесь я имею ввиду применение в Windows PKI), где эти политики определены.

Заметка: всякие верисайны, тафты и прочие коммерческие CA как правило применяют 1-2 уровневые (хотя есть и 3-х уровневые) иерархии. Но у них специфика другая.

Если всё так просто умещается в 2-х уровневой иерархии, когда же нам может понадобиться выделенный Policy CA?

Когда применяем 3-х уровневую иерархию?

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

Например, в России у вас головной офис, а в Европе у вас находится филиал. В этом случае у вас скорее всего политики выдачи для родной страны и Европы будут очень сильно отличаться, потому что законодательства в этих странах тоже разные. Но и здесь возможны варианты. Если все CA находятся в головном офисе (и европейский офис подключается к головному через VPN), вы можете рассмотреть предыдущий раздел. Это означает, что вы сделаете 2 издающих CA: один для локального офиса, второй для европейского. Естественно, на каждом CA будут описаны различные политики сертификатов.

Если же в европейском филиале находится свой CA и им управляет местный персонал, тогда понадобится выделенный Policy CA. Т.е. вы в головном офисе установите Policy CA, ограничите его на уровне CPS и тогда европейский офис может спокойно управлять своими издающими CA без риска нарушить политики сертификатов. При этом, для головного офиса вы можете использовать 2-х уровневую иерархию. Разумеется, в этом случае для Policy CA вы не сможете использовать All Issuance Policies, а нужно применить свой кастомный OID (или несколько, см предыдущий раздел).

Схожий сценарий: у вас есть большое количество филиалов, в каждом установлен свой издающий CA (но все они подчинаются одному корневому CA), т.к. интернеты между ними не очень шустрые и стабильные. И каждым CA в филиале управляет своя команда администраторов. В этом случае есть смысл (но совершенно не обязательно) под корнем установить Policy CA, на нём определить CPS и уже под ним размещать издающие CA филиалов. В этом случае от администраторов филиалов не требуется лишних телодвижений по прописыванию CPS в CAPolicy.inf, потому что CPS определённые на Policy CA будут наследоваться на сертификаты издающих CA.

Следующий сценарий, более специфический: вы хотите сделать root signing. Root signing — это когда коммерческий CA (VeriSign, Thawte, etc) выдаёт сертификат для вашего CA. В этом случае вы исключаете проблему организации доверия вашим сертификатам, потому что все сертификаты в этом случае будут заканчиваться корневым CA верисайна или какого-нибудь другого well-known коммерческого CA. В этом случае коммерческий CA выдаст сертификат для вашего выделенного Policy CA, который не может быть совмещён с издающим (это одно из требований к root signing).

Ещё один специфический сценарий: в вашей компании несколько лесов Active Directory. Если вы не применяете cross-forest enrollment, вам вероятнее всего придётся сделать выделенный Policy CA, который определит общую политику сертификатов для всех лесов Active Directory. И в каждом лесу уже устанавливаете издающие CA. Если же каждый лес будет иметь свой независимый набор политик сертификатов, можно ограничиться двумя уровнями.

Последний сценарий в этом разделе: вы планируете кросс-сертификацию с другой PKI. При этом под кросс-сертификацию должны подпадать все ваши издающие CA. В этом случае у вас есть выбор — оставаться на 2-х уровнях и получить на каждый CA по кросс-сертификату или сделать выделенный Policy CA и тогда получите только 1 кросс-сертификат. Вы можете сказать, что можно же получить один кросс-сертификат для корневого CA и тогда все издающие CA будут подпадать под кросс-сертификацию. С одной стороны это действительно возможно. Но кросс-сертификация подразумевает наличие CPS (а так же возможны внешние аудиты на предмет следования собственному CPS), который никогда на корневых CA не определяется.

Итоги

Про 4-х уровневую иерархию я ничего рассказывать не буду, потому что не посчастливилось лицезреть такое. Если что, можете прочитать об этом в книге Комара —http://www.sysadmins.lv/pkibookshelf.aspx. А мы, в свою очередь, немного освежили память об иерархиях в PKI и более детально рассмотрели некоторые аспекты, касающиеся Policy CA и разрушили миф о бест-практичности 3-х уровневой иерархии. Т.е. каждая PKI строится с учётом требований бизнеса и управления, а не бизнес и управление строятся под конкретную выбранную иерархию и этот пост лишь раскрывает некоторые аспекты, которыми можно руководствоваться для проектировании PKI.

В любом случае, как сделаете — так и будет хорошо. Лишь бы вы (как проектировщик PKI) подошли к делу с головой и ваше решение заработало, как запланировало.

Недавняя тема «Мифы о мифах» подтолкнула меня к очередному эпосу на тему мифов в целом и PKI в частности. Основная мысль заключается в том, что частный результат может быть очень даже противоположным общему. Хоть фундамент PKI и выглядит монолитным, его основание закладывается из множества составных деталей. И, следуя указанной мысли, одна деталька не всегда соответствует конечному итогу.

Возьмём один абстрактный пример: администратор X нашёл способ обхождения ограничения RFC (RFC5280, §4.2.1.9) путём подписания пользовательским сертификатом (например, сертификатом EFS или secure email) другого сертификата. Здесь нужно дать большое пояснение сути проблемы.

В бытность использования сертификатов версии 1 было отмечено множество проблем. Например, невозможно было определить тип сертификата — конечный сертификат или сертификат промежуточного CA. Так же было невозможно узнать для каких целей может использоваться сертификат (например, только для шифрования файлов). Нельзя было проверить сертификат на отзыв, если CRL издателя не установлен (закеширован) в системе. Так же, проблемы начинались при обновлении сертификатов самих CA. Вобщем, проблем было много и гибко использовать сертификаты не представлялось возможным. Версия 2 решила только одну проблему — обновление сертификата CA. И только сертификаты версии 3 стали способны решить многие проблемы тех времён. Это было достигнуто за счёт появления расширений сертификата. Расширения сертификатов могут содержать всевозможную информацию о самом сертификате, издателе, владельце ключа и т.д. Например, мы можем применить расширение Enhanced Key Usage и на основании его содержимого принимать решение, можно ли использовать предъявленный сертификат для конкретной задачи или нет. Например, в правильном мире ни одно приложение (rfc-conformant) не согласится использовать сертификат с EKU = Encrypting File System для установки цифровой подписи и т.д. Дальнейшая дискуссия пойдёт только о сертификатах версии 3.

Вернёмся же, к нашему вопросу. Согласно RFC5280, §4.2.1.9, подписывать сертификаты можно только сертификатом, которое содержит расширение Basic Constraints и свойство cA (certification authority) выставлено в true. Так же это расширение должно быть помечено как критичное. Если одно из этих условий не выполняется, такой сертификат не может использоваться для подписи других сертификатов (условно говоря, выступать в роли CA). Но пытливые умы находят лазейку (в виде утилит вида openssl, makecert или низкоуровневых API) и подписывают пользовательским сертификатом другой сертификат. Слабонервные могут впасть в панику, хвататься за острые и режущие предметы или выбрасываться из окон верхних этажей небоскрёбов, потому что мир рухнул. Они так верили в PKI, а тут какой-нибудь openssl взял и дискредитировал всю нерушимую идею PKI. Необходимо как-то запретить такие вольности.

Но я спешу успокоить вас. PKI существует очень давно и сегодня подобные фокусы не пройдут. Давайте посмотрим, как это выглядит на картинках. Я взял свой сертификат, предназначенный только для Code и Document Signing и подписал другой сертификат:

This certificate is not valid for the selected purpose #1

посмотрим вкладку Certification path:

This certificate is not valid for the selected purpose #2

А тут конечный сертификат ВНЕЗАПНО is Ok. Правда, можно заметить, что на предыдущем сертификате в цепочке стоит треугольничек. Когда я запустил файл, Windows пропустил сертификат через упрощённый движок построения цепочки (certificate chaining engine или сокращённо CCE). Поскольку CCE очень любит rfc и не любит openssl, он задетектировал ошибку, что предъявленный сертификат не может использоваться для указанного применения. Но мы пока не видим, каким боком тут вырос Basic Constraints. Для этого мы воспользуемся certutil'ом и посмотрим более детальный трейс CCE (публикую только отрывок):

ChainContext.dwErrorStatus = CERT_TRUST_IS_NOT_VALID_FOR_USAGE (0x10)
ChainContext.dwErrorStatus = CERT_TRUST_INVALID_BASIC_CONSTRAINTS (0x400)

вот тут мы и видим, что проблема с Basic Constraints. Дело в том, что мой сертификат подписи не содержит этого расширения, следовательно не может использоваться для подписывания других сертификатов. Вот описание этой ошибки по версии MSDN:

The certificate or one of the certificates in the certificate chain has a basic constraints extension, and either the certificate cannot be used to issue other certificates, or the chain path length has been exceeded.

Следовательно, если предъявить подобный сертификат любому приложению, которое использует rfc-conformant certificate chaining engine (будь то встроенный в Windows или что-то своё), приложение должно очень сильно ругнуться на сертификат и отклонить его.

Какая следует мораль из этой истории? Мораль, мне кажется, такова, что технически невозможно запретить пользователям делать какие-то нехорошие вещи (например, описываемый сценарий). Но будет крайне сложным доказать какому-то приложению, что вы всё сделали хорошо (разве что если вы Чак Норрис). Потому что приложения действуют по своим правилам (в пределах соответствия стандартам) и они не любят тех, кто эти стандарты пытается нарушать.

Напоследок, предлагаю ссылки на указанные сертификаты, если кто-то хочет заняться анализом вопроса самостоятельно.

В разных интернетах разные пользователи доставляют разные заблуждения на тему PKI. Это вполне нормальное поведение для тех, кто не является специалистом в этой области. Но ненормальное для пользователей претендующих на это звание. Сегодня на повестке дня 3 вопроса:

  • Standalone CA и шаблоны сертификатов;
  • тайна самоподписанных сертификатов EFS;
  • сертификаты на кластере NLB.

Standalone CA и шаблоны сертификатов

Вчера в одном блоге вычитал утверждение, что Standalone CA может использовать шаблоны сертификатов. На самом деле это не так. Standalone CA выгодно отличается от Enterprise, что ему не нужны шаблоны. Совсем. Он собирает сертификат из той информации, которая хранится в запросе сертификата. Если в оснастке certsrv.msc у Enterprise CA есть секция Certificate Templates, то у Standalone CA её нет:

Standalone CA

вот, есть Revoked, Issued certificates, Pending, Failed Requests, но никакого Certificate Templates, так что использовать их в такой ситуации нельзя.

Тайна самоподписанных сертификатов EFS

Я думаю, что многие шифровали файлы в системе простым, автоматически сгенерированным системой сертификатом. Находится он в оснастке certmgr.msc, контейнере Personal и выглядит примерно так:

Self-signed EFS certificate

Как мы видим, это самоподписанный сертификат, у которого Issuer и Subject одинаковые и соответствуют имени текущего пользователя. Срок действия — 100 лет. Всем известно, чтобы сертификат был доверенный, корневой сертификат из его цепочки (или он сам, если это самоподписанный сертификат) должен находиться в контейнере Trusted Root CA. Но в случае с этим сертификатом EFS такое не наблюдается. И вчера в том же самом блоге узнал, что этот самоподписанный сертификат какой-то волшебный и на него не распространяются правила доверия.

Но на самом деле всё гораздо интересней. PKI — технология очень железная с не менее железной логикой и всё в ней подчиняется простым принципам. Это делает PKI весьма надёжной и непробиваемой. Но давайте вернёмся к нашим баранамсампоподписанным сертификатам EFS. На самом деле его копия тоже установлена в контейнере, который делает сертификаты доверенными. И имя ему Trusted People:

Trusted People

Если удалить ваш сертификат из контейнера Trusted People, он станет недоверенным и мы будем горько плакать по этому поводу. Вот что говорят об этом технеты:

Trusted People (TrustedPeople) — This container keeps certificates issued to people or end entities that are explicitly trusted. Most often, these are self-signed certificates or certificates explicitly trusted in an application such as Microsoft Outlook. To share an EFS–encrypted file with other parties, you must have their certificate in this store.

Иными словами, контейнер Trusted People своего рода аналог контейнера Trusted Root CAs, но только для пользовательских сертификатов.

Сертификаты на кластере NLB

Предположим, у вас кластер NLB, который несёт роль веб-сервера. Зачастую там будет какой-нибудь HTTPS, которому нужны сертификаты. Бытует весьма устойчивое мнение, будто бы сертификат SSL должен быть одинаковый на всех узлах кластера, иначе что-то не будет работать при отказе какого-то узла. В действительности это тоже весьма далеко от истины. Дело в том, что сессионные ключи не реплицируются между узлами кластера и каждый узел поддерживает свою сессию SSL c клиентом (это реально, когда клиент одновременно подключен к нескольким узлам кластера). И переключение с одного узла на второй (если один отказал) вызывает инициирование новой сессии SSL. Т.е. снова запрос сертификата сервера, проверка на доверие и отзыв, генерация сессии, сессионных ключей и всё остальное.

Следовательно, каждый узел кластера может поддерживать свой собственный сертификат SSL. И это, между прочим, является бест практисом (возможно проплаченный верисайном с тафтом). Бест практис в данном случае заключается в том, что каждый узел кластера запрашивает для себя свой сертификат и нет необходимости экспортировать ключи в PFX. Потому что когда люди копируют ключи в PFX защищая его простеньким паролем. Или сложным, но записывая пароль на бумажке, которая попадает нежелательному пользователю, ну а остальное вы знаете :-)

На сегодня это всё.

Update 20.03.2011: исправлен синтаксис для INF


В различных интернетах ходит достаточно много слухов о правильности использования флага EDITF_ATTRIBUTESUBJECTALTNAME2. В общем смысле, администраторы включают этот флаг для выпуска сертификатов с расширением Subject Alternative Name без разбора и ссылаются на этот документ: http://support.microsoft.com/kb/931351. Но, как оказывается, мало кто осилил документ полностью.

Как видно из названия (ATTRIBUTE), этот флаг разрешает сабмитить запрос сертификата с атрибутом, содержащим расширение SAN. Этот атрибут можно добавить следующими способами:

  • при использовании Web Enrollment Pages (Windows 2000 и Windows Server 2003) вы можете указать дополнительный атрибут с использованием примерно такого формата: san:dns=dns.name[&dns=dns.name];
  • при использовании certreq и INF файла, который содержит строку следующего формата: san:dns=dns.name[&dns=dns.name] (такой же, как и в Web Enrollment Pages);
  • при использовании certreq и сабмита уже готового файла запроса: certreq –submit –attrib:"san:dns=dns.name[&dns=dns.name]"

С одной стороны, вроде, и удобно, но это сильно небезопасно. Дело в том, что если флаг EDITF_ATTRIBUTESUBJECTALTNAME2 включен, любой пользователь можешь добавить атрибут SAN к своему запросу и получить нужный сертификат, даже если шаблон не разрешает использовать расширение SAN. Данный флаг можно включать только если CA сконфгирурирован на ручное одобрение каждого запроса администратором CA, который будет следить, чтобы ни один пользователь не подсунул «левый» SAN. Но в условиях энтерпрайза это малореально. Следовательно вы НЕ ДОЛЖНЫ включать этот флаг на Enterprise CA, если он настроен на автоматическую выдачу сертификатов без премодерации!

Но мы ведь хотим SAN, но не хотим включать этот флаг. Как тогда быть? Для этого мы (и вы тоже) должны использовать один из следующих методов:

  • Сжечь Web Enrollment Pages и научиться пользоваться оснасткой Certificates (в Windows Vista и выше) для получения сертификата: Web server certificate enrollment with SAN extension (ха-ха, у меня там раньше тоже была сноска на включение этого флага, потому что сам заблуждался).
  • Использовать новые возможности INF файла. Начиная с Windows Vista вы можете в INF файле указать расширение SAN в Base64 кодировке с использованием примерно следующего формата:
    [Extensions] 
    2.5.29.17 = "{text}"
    _continue_ = "dns=www01.fabrikam.com&"
  • настроить шаблон на премодерацию и использовать вот такой скриптик для добавления расширения SAN в запрос: How to add FQDN to HP iLO request

HTH