Техническое: проверка HPKP в браузере

HPKP (HTTP Public Key Pinning) – технология, позволяющая привязать к серверу открытый ключ. Для этого служит специальное поле в заголовках HTTP. Я писал про HPKP на dxdt.ru ранее. Как и в случае практически любой технологии обеспечения информационной безопасности – интересно посмотреть, как реализация работает в деталях. Для этого я добавил HPKP на “тестовую площадку”: 1d.pw.

Напомню, кратко, как эта технология работает. При первом визите на сайт по HTTPS браузер запоминает отпечаток некоторого ключа, который передаётся в заголовке; это может быть отпечаток серверного ключа (так, например, сделано на dxdt.ru) или любого другого ключа, входящего в цепочку валидации сервера (можно добавлять ключи сертификатов удостоверяющих центров и так далее). При повторном соединении с сайтом по TLS браузер проверяет, что какой-то из ключей, предъявленных сервером, соответствует ранее записанному отпечатку. Если найти такой ключ не удалось, выдаётся сообщение об ошибке и соединение не устанавливается (именно этот вариант воспроизведён на тестовой площадке). Ситуация напоминает случай, когда браузер не смог провести успешную валидацию цепочки SSL-сертификатов, с той лишь разницей, что привязывание ключа позволяет защитить соединение от перехвата при помощи валидных сертификатов.

Отлаживать HPKP непросто. Запись отпечатка производится только в том случае, если браузер успешно установил соединение по TLS и получил ответ с корректно форматированным полем Public-Key-Pins – то есть, требуется работающий по TLS веб-сервер с валидным SSL-сертификатом. Для того, чтобы вызвать ошибку проверки отпечатка также требуется валидный сертификат: иначе браузер выдаст сообщение об ошибке раньше, чем доберётся до проверки отпечатков. При этом требуется серверный сертификат, выпущенный для другого ключа, отличающегося от “правильного”. Как-то узнавать браузер на сервере, чтобы имитировать подмену ключа, – не получится: проверка отпечатка происходит на самом раннем этапе установления TLS-соединения, ни куки-файлы, ни какие-то ещё данные “уровня приложения” к этому моменту переданы не будут. Идентифицировать по IP-адресу в наше время NAT-ов и прочих трансляторов – тоже неправильно.

Я поступил следующим образом. По адресу https://1d.pw/ откликается веб-сервер, который передаёт заголовок с отпечатком ключа и флагом, обозначающим, что отпечаток действителен для всех поддоменов (ниже я привожу поле Public-Key-Pins для 1d.pw полностью). А по адресу https://pin.1d.pw/ – откликается другой виртуальный хост, который использует другой серверный ключ (но в паре с валидным сертификатом). Если ваш браузер ещё не был на 1d.pw, то вы можете с его помощью успешно посетить pin.1d.pw. Однако если ваш браузер зайдёт на https://1d.pw/, то он запомнит отпечаток ключа. Если после этого попытаться открыть https://pin.1d.pw/, то должно появиться сообщение об ошибке (“невозможно установить защищённое соединение” или подобная формулировка) – это означает, что HPKP поддерживается браузером. Время жизни отпечатка указывается в поле Public-Key-Pins – для 1d.pw это 3600 секунд (или 1 час).

Вот заголовок HPKP:

Public-Key-Pins:pin-sha256=”afLVIYy6nD4LIkratYg295p89kYfqChllWQGYs7K8/A=”; pin-sha256=”K/QRriVzZo54i+9qeLPgP+22zWsL4rMZGFU9F0QJn/M=”; max-age=3600; includeSubdomains; report-uri=”http://hpkp-reporter.dxdt.ru/api/hpkp.pl”

Здесь есть ещё один интересный элемент – report-uri. Это адрес, по которому браузер передаёт сообщение о неудачной проверке отпечатка ключа (POST-запрос с данными в формате JSON). Я поднял отдельный обработчик для этих сообщений (планирую вынести его на другой домен и подключить, в том числе, к HKPK на dxdt.ru). Пока что данная функция работает только в Chrome, но это весьма распространённый браузер, поэтому, в теории, можно будет увидеть попытки перехвата TLS-соединений.

Посмотрим, как использование HPKP будет развиваться дальше.

Адрес записки: https://dxdt.ru/2015/12/22/7780/

Похожие записки:



Далее - мнения и дискуссии

(Сообщения ниже добавляются читателями сайта, через форму, расположенную в конце страницы.)