Original:http://noncombatant.org/2015/05/01/about-http-public-key-pinning/

О закреплении публичного ключа

Введение

Наконец, Целевая группа Internet Engineering Task Force (IETF) опубликовала RFC 7469, Расширение открытого ключа для HTTP (HPKP). Благодаря моим коллегам Райану Слейви, Адаму Лэнгли и Крису Эвансу за то, что он придумал эту идею; и благодаря Райану и Крису Е. за то, что он помог мне написать много проектов, которые предшествовали окончательному RFC. Спасибо также многим участникам IETF, которые прокомментировали проекты и помогли отложить документ до статуса RFC.

Что такое закрепление, и что оно решает?

HPKP является попыткой решить одну из больших проблем в веб-PKI : тот факт, что по существу любой центр сертификации (CA) или промежуточный эмитент могут выдавать сертификаты конечного объекта (EE или «leaf») для практически любого веб-сайта. Например, несмотря на то, что сертификат для mail.google.com выдается «Google Internet Authority G2», который, в свою очередь, выдается корневым CA «GeoTrust Global CA», неясный голландский CA также может попытаться выдать сертификаты для почты .google.com . Таким образом, нам бы очень хотелось, чтобы клиенты не могли доверять таким ошибочным сертификатам.

Средство просмотра сертификатов Chrome, показывающее цепочку выпуска mail.google.com.

 

Средство просмотра сертификатов Chrome, показывающее цепочку выпуска mail.google.com.

Часто люди предлагают решить эту проблему путем разделения сети: либо они хотели бы настроить своих клиентов, чтобы доверять только ЦС из своей собственной страны; или они хотели бы, чтобы ЦС страны X были запрещены к выдаче сертификатов для организаций из стран Y и Z ; или оба. Есть пара проблем с этим. Существенно, что Интернет по своей природе является всемирным, и его многочисленные большие выгоды вытекают из этого. Кроме того, не всегда ясно, какая нация у данной организации действительно «от», и, следовательно, не всегда ясно, что CA «должен» выдавать сертификаты организации.

Не может быть идеального набора «золотых корней» - вы не можете создать минимальный набор сертификатов выдачи, чьи операторы более уверены, чем какой-либо другой набор, который не будет ошибочно выдаваться (будь то по назначению или случайно). Если вы разделяете сеть, вы уменьшаете ее стоимость, не уменьшая при этом угрозу неправильной выдачи. Поэтому нам нужно что-то еще.

HPKP - это 1 способ сделать это. HPKP позволяет веб-серверу сообщать клиентам (например, браузерам), что сервер всегда будет представлять в своей цепочке сертификатов X.509 не менее 1 набора открытых ключей; и в противном случае отклонить цепочку сертификатов. Таким образом, оператор веб-сайта может эффективно сократить набор эмитентов, которые могут выдавать для своего сайта, без разбиения сети.

Как работает Pinning?

Чтобы понять ключевое закрепление, сначала рассмотрим классический простой случай: управление ключами SSH. Когда вы впервые подключаетесь к SSH-серверу с клиентом, который не знает о сервере раньше, вы увидите следующее:

chris@goatbeast:~ $ ssh freebsd
The authenticity of host 'freebsd (10.0.0.4)' can't be established.
ECDSA key fingerprint is b0:79:74:0f:58:20:80:fd:c7:47:33:d6:9c:40:df:20.
Are you sure you want to continue connecting (yes/no)? 

Мой сервер, freebsd, представляет свой открытый ключ клиенту SSH, чтобы подтвердить его личность. Проблема заключается в том, что мой клиент не знает об этом ( имя сервера , открытый ключ ). Поэтому он просит меня устранить путаницу. Я должен выполнить некоторую внеполосную проверку правильности ключевого отпечатка пальца и сказать «Да» или «Нет».

Предполагая, что я говорю «Да», мой клиент впредь будет ожидать, что этот сервер представит этот ключ и только тот ключ . Если на моем сервере когда-либо появляется другой ключ - из-за законного поворота ключа или фактической сетевой атаки - мой клиент откажется подключиться и напечатает сообщение следующим образом:

No ECDSA host key is known for freebsd and you have requested strict checking.
Host key verification failed.

Причина, по которой это работает в SSH, заключается в том, что почти каждый, кто использует SSH, является экспертом: системным администратором, инженером декомплексов или инженером-программистом. Они понимают сообщение об ошибке, знают, что делать в случае сбоя проверки ключа, и могут действовать на него. Сообщество людей, использующих любой сервер, невелико. Они могут просто разговаривать друг с другом: «Эй, ты вращал ключи для сервера?»

Но на всемирной паутине это не полетит. Ключевое вращение является общим, нам требуется введение без трения для этого первого соединения, и люди, использующие браузеры, не имеют специальных знаний о криптографической аутентификации. Поэтому мы все равно должны полагаться на ЦС для обеспечения внедрения, и мы по-прежнему используем цепочки сертификатов, чтобы обеспечить гибкую непрерывность для криптографических идентификаторов наших веб-серверов. И вместо того, чтобы фиксировать один ключ конечной сущности, как в SSH, мы можем связать набор ключей - возможно, в нескольких местах в цепочке сертификатов. Как мы увидим ниже, это может значительно повысить надежность.

Проверка подлинности HPKP Pin по существу представляет собой пересечение : учитывая набор открытых ключей в цепочке подписанных сертификатов, любые из них такие же, как любой из ключей, которые сервер утвердил («приколол») как хорошо известный? Если это так, проверка контакта успешно завершена; если нет, клиент должен вести себя как клиент SSH: отбросить недействительное соединение. В Chrome это выглядит так:

Снимок экрана Chrome, отклоняющий недействительный набор контактов.
Chrome отклоняет неверный набор контактов.

Как настроить HPKP для моего сайта?

ПРЕДУПРЕЖДЕНИЕ. Привязка открытого ключа для веб-сайтов может быть очень опасной. Если вы допустили ошибку, вы можете заставить клиентов закрепить набор ключей, которые проверяются сегодня, но которые перестают проверять неделю или год, если что-то изменится. В этом случае вы в конечном итоге откажете в обслуживании своего сайта! Люди не смогут подключиться. (Мы называем это «кражу вашего сайта».) Если вы не уверены в том, что понимаете веб-PKI, и если вы не уверены в том, что сможете эффективно использовать криптографическую идентификацию своего сайта, вы не должны использовать ключевое закрепление. Придерживайтесь регулярной, незакрепленной веб-PKI, пока не получите больше уверенности.

Вы должны предпринять несколько шагов, чтобы вывести 1 или более открытых ключей в цепочке сертификатов вашего сайта:

  1. Выявите цепочку сертификатов вашего сайта, которые обслуживаются и проверяются клиентами
  2. Решите, где в цепочке (-ях), которую вы хотите
  3. Настройка 1 или более резервных контактов
  4. Настройте ваш (тестовый) сервер для выпуска недолгого заголовка HPKP и проверьте его
  5. Постепенно увеличивайте срок службы штыревого набора, когда вы будете более комфортно с ним

В следующих разделах я расскажу, как делать каждый шаг.

Определите цепочку сертификатов вашего сайта

Как мы видели на скриншоте в окне просмотра сертификатов, сертификат сайта находится в конце цепочки (обычно) не менее 3 сертификатов: корневого сертификата или доверенного знака , 1 или более промежуточных сертификатов эмитента и, наконец, сертификата конечного объекта . Как правило, веб-сервер должен служить частью своего TLS-подтверждения всех этих сертификатов, за исключением корневого или доверительного привязки - клиент поддерживает набор доверенных привязок и находок 1, которые подписали самый верхний промежуток. В некоторых случаях сервер может обслуживать только его EE, и клиенты будут обнаруживать промежуточных эмитентов, но это часто приводит к проблемам. Как правило, предполагается использовать цепочку, содержащую промежуточный эмитент (ы).

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

Существенно, что клиенты выполняют проверку PIN-кода в цепочке, которую они строят во время проверки цепи, что не обязательно совпадает с цепочкой, которую вы обслуживаете. Таким образом, к сожалению, вы не всегда можете просто прикрепить ключи в цепочке, которую вы обслуживаете, и быть уверенным, что проверка PIN-кода будет успешной. (Хотя см. Следующий раздел о способах получения лучшего покрытия.)

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

Решите, какие клавиши для вывода

Теперь, когда у вас есть контроль над тем, какие клиенты будут создавать и проверять клиентскую цепочку, пришло время решить, где в этой цепочке закрепить. Для обсуждения я возьму на себя простую модель развертывания сервера:

Таким образом, у нас есть две цепочки сертификатов в производстве: CA → посредник → EE1 и CA → посредник → EE2. Серверы из 2-х кластеров настроены правильно, чтобы обслуживать посредники цепей → EE1 (для центра обработки данных 1) и посредника → EE2 (для DC 2).

Давайте далее предположим для простоты, что клиенты действительно создают путь через посредника к тому же сертификату CA, который мы ожидаем. (Опять же, в действительности вы не можете просто предположить это .)

Мы можем назначить ключи любого из 4-х сертификатов: CA, посредника, EE1 и EE2. Последствия закрепления на разных уровнях различаются:

Закрепление в EE (s).
Это дает оператору сайта гарантию безопасности, столь же сильную, как SSH: любая ошибка приведет к тому, что клиенты откажутся от сети с неправильным назначением. Недостатком является то, что оператор сервера связан с этими конкретными открытыми ключами EE - просто получение новой EE, выпущенной одним и тем же эмитентом (-ами), не будет работать (хотя см. Ниже о резервных выводах).
Закрепление у посредников.
Это уменьшает угрозу ошибочного использования только закрепленным посредникам - значительное улучшение по сравнению с статус-кво, но не так сильно, как привязка только к ЭО. Точно так же любой новый сертификат, выданный этим сайтом этими эмитентами, будет проходить проверку PIN.
Закрепление корней (корней).
Это похоже на привязку к посредникам. Часто одна и та же организация контролирует закрытые ключи корня и посредников. Если это не так, то эта опция будет отличаться от привязки к посредникам: оператор сайта теперь доверяет больше или другим владельцам закрытых ключей не ошибиться.

Путем закрепления на нескольких уровнях в цепочке сертификатов - например, EE и посредников, EE и корень, посредники и корень, или вообще 3 - оператор сайта может торговать доверием большего числа эмитентов с большей легкостью избегать сайт.

Создать резервный штырь

RFC обязывает, что хосты ДОЛЖНЫ предоставить резервный контакт: штырь, который отсутствует в цепочке, которую клиент проверяет. Это для вашего же блага: если вы потеряете контроль над вашими личными ключами и вам нужно заново закрепить свой сайт и получить новые сертификаты, вы не хотите, чтобы на вашем сайте было время простоя - и, конечно же, не нужно было кирпича! Если клиенты уже не привязали ваш резервный ключ, ваш сайт будет замаскирован до истечения максимального времени.

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

Этот скрипт генерирует новый ключ и связанный с ним запрос подписи сертификата (CSR, который вы отправляете в ЦС для их подписания). Это способ генерации первичного и / или резервного ключа EE и CSR для вашего сайта. Опять же, самое безопасное дело - фактически получить свой резервный ключ в действительном сертификате, выпущенном реальным эмитентом, чтобы вы могли немедленно его выпустить в производство, если это необходимо.

#!/bin/sh

openssl genrsa -out "$1".key 2048
openssl req -new -key "$1".key -out "$1".csr

Тестирование Заголовок HPKP

Этот скрипт делает ключевой вывод: он читается либо в сертификате X.509 (в формате PEM), либо в запросе подписи сертификата (также в формате PEM), извлекает раздел с открытым ключом (SPKI) для объекта, хеширует SPKI с SHA- 256, а затем база 64-кодирует:

#!/bin/sh

type="x509"
case "$1" in
  x509)
    type="x509"
    ;;
  req)
    type="req"
    ;;
  *)
    echo "Usage: $0 x509 certificate-pathname"
    echo "       $0 req certificate-signing-request-pathname"
    exit 1
esac

openssl $type -noout -in "$2" -pubkey | \
  openssl asn1parse -noout -inform pem -out public.key
openssl dgst -sha256 -binary public.key | openssl enc -base64

Результат этого скрипта - это то, что вы поместите в свои заголовки PKP. Например, это пример директивы заголовка Apache, которую я в настоящее время использую для nonfreesoftware.org (строки, сложенные для соответствия):

<pre>Header add Public-Key-Pins "max-age=500; includeSubDomains;
pin-sha256=\"wBVXRiGdJMKG7vQhr9tZ9br9Md4l7cO69LF2a88Au/o=\";
pin-sha256=\"fv1+PWVvrBGKldX8uRtODY3sDbBKlsJOa48mI9s+6Mk=\";
pin-sha256=\"lT09gPUeQfbYrlxRtpsHrjDblj9Rpz+u7ajfCrg4qDM=\""
</pre>

Я привязал свой конечный объект, эмитент и резервный ключ. Я установил максимальный возраст на 500 секунд, так что я не могу надолго заманить сайт. И, конечно же, я привязал только альтернативное имя для сайта, а не каноническое имя (которое является noncombatant.org).

Наконец, проверьте, чтобы ваш клиент прочитал и понял ключевые контакты. На этом снимке экрана вы можете увидеть, что Chrome распознал заголовок с открытым ключом:

Вид chrome: // net-internals / # hsts, показывающий ключевые контакты для nonfreesoftware.org
chrome://net-internals/#hsts позволяет запрашивать состояние базы данных HSTS и HPKP.