Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
Пишут, что и регистратор GoDaddy удалит аккаунты с российскими адресами. Я тоже получил такое сообщение из GoDaddy. Впрочем, я оттуда всё даже минимально нужное и так давно унёс – больше года назад. Конечно, переносить домены от такого регистратора нужно в любом случае и всем (а не только получившим письмо – подобная ситуация “отключения аккаунта” всегда может поменяться, а условия – расшириться), но это самая очевидная часть. Да, переносить зарегистрированные домены имеет смысл к российским регистраторам, это тоже понятно. Всё указывает на то, что глобальную Сеть активно сегментируют. Такая сегментация – это самостоятельный трансграничный процесс, имеющий несколько более сложную структуру, чем можно прочитать в СМИ. Поэтому нельзя исключать, что в скором времени и иностранные реестры открытых доменов верхнего уровня начнут массово вводить аналогичные ограничения непосредственно для администраторов (для регистраторов они уже, в принципе, действуют, но там есть “способы и оговорки”).
Комментарии (1) »
Небольшой комментарий о привычных форматах и способах записи TLS-сертификатов (SSL-сертификатов, как почему-то некоторые продолжают называть). Такой сертификат представляет собой публичный электронный документ, состоящий из множества полей. Внутри эти поля записываются в так называемой ASN.1-структуре, которая, в общих чертах, является иерархией вложенных строк байтов. Общий принцип кодирования здесь такой: строка всегда начинается с префикса, точно задающего тип поля данных и длину данных, а оставшиеся байты – несут сами полезные данные. С базовыми, независимыми от платформы, способами записи связаны разные тонкости, исторически сложившиеся “допущения”, а также и всякие прочие спецификации, например, DER (Distinguished Encoding Rules). Однако реальные хитрости и сложности, происходящие из интерпретации упомянутых схем/спецификаций, возникают только у разработчиков программного обеспечения, которое существенным образом использует данные TLS-сертификатов, но не у пользователей. Например, содержимое файла сертификата в удобном формате PEM выглядит, примерно, так (но тут, для удобства, удалена большая часть строк):
-----BEGIN CERTIFICATE----- MIIEDjCCAvagAwIBAgISBB+ebYSbzCVbUmAq3rUH97bcMA0GCSqGSIb3DQEBCwUA MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD [...] JaRB6DTHZdmM0MzOf6ltVn48cE8LVUuTAM7cFcw+Z1a40XlrMj0nY6Et+QDTZ1n+ 2QZDaj5N+G21wxqvpj29BusHurW0xpFIM/Iv2+A8sX+IWQ== -----END CERTIFICATE-----
Никакой сложности или “криптографии” конкретно тут, в способе записи сертификата, нет. Если не использовать нарочито строгие формулировки, то PEM – это просто текстовый формат с base64-кодированием, переводами строк на заданной границе и строками-разделителями, которые определяются пятью символами “минус” с BEGIN/END. В данном случае:
"-----BEGIN CERTIFICATE-----"
и
"-----END CERTIFICATE-----".
Между этими строками находится просто base64-запись байтов сертификата, закодированного в DER (можно считать, что в “бинарном” виде, а не в “тексте”). Если взять байты сертификата, закодировать их в base64, поместить результат в текстовый редактор, дописать “BEGIN…END” в заданном формате с минусами, добавить переносы строк, то получится PEM. И наоборот. (Исключения, наверное, можно попробовать придумать, но они будут экзотическими.) Естественно, так как сертификат содержит внутри электронную подпись, то значения всех его битов – важны: если что-то изменится, то подпись перестанет сходиться (или вообще проверяться, если испорчена сама запись подписи).
Преобразовать сертификат между текстовым PEM и “бинарным” DER можно при помощи OpenSSL:
PEM -> DER $ openssl x509 -in cert.pem -out cert.der -outform DER DER -> PEM $ openssl x509 -in cert.der -out cert.pem -inform DER -outform PEM
(Опция “-inform DER” во втором случае нужна потому, что openssl x509 по умолчанию ожидает формат PEM.)
В сертификате при этом ничего не изменяется, никаких особо сложных операций не выполняется, а OpenSSL здесь нужен только как удобная утилита “всё в одном”. Аналогичного эффекта, действуя через командную строку, нетрудно добиться и сочетанием cat с base64 -d.
Комментировать »
Перемешивание – это само собой, однако есть и другой важный аспект наложенных сетей, встраиваемых в веб-браузеры: внутрь такой сети будут затягиваться и серверы, публикующие информацию, предоставляющие сервисы пользователям (веб-серверы, а также разные бэкенды “облачных” приложений).
Мотивировать такой ход несложно: узлы, находящиеся внутри наложенной сети, “будут ближе к пользователю”, “лучше защищены”, “станут лучше ранжироваться в выдаче поисковых систем”, кроме того, и доступ проще оптимизировать. “Внутри” – означает, что на узлах провайдера выходных шлюзов, при том, что эти узлы принадлежат логической перемешивающей сети. Естественным примером из практики являются скрытые TOR-сервисы. Занятно, что если речь будет идти на уровне Google, то даже можно отказаться от “общепринятой” DNS – система имён и адресов может быть своей, а вход на сервисы и сейчас нередко происходит через поисковый запрос, даже из браузера. А браузер Chrome, например, более чем достаточно распространён для того, чтобы администраторы популярных сервисов задумались о параметрах доступа пользователей этого браузера, ну, это кроме только что перечисленных “прочих преимуществ”.
Комментировать »
На OpenNET пишут про RFC для децентрализованной системы имён GNS:
“Использование Curve25519 воспринимается некоторыми как весьма странный шаг, так как для ECDSA применяют другие типы эллиптических кривых, а в паре с Curve25519 обычно используют алгоритм цифровых подписей Ed25519, более современный, более безопасный и более быстрый, чем ECDSA. С точки зрения криптостойкости в том числе вызывает сомнение выбор размера закрытого ключа – 32 байта вместо 64 байт”
В GNS, действительно, используют ECDSA на кривой Curve25519. Это может, конечно, показаться странным. Однако алгоритм ECDSA работает в группе точек и вообще не зависит от выбора кривой (да, даже про “суперсингулярные кривые” тут есть занятные уточнения). Поэтому ничто не мешает взять Curve25519 вместо, например, более привычной P-256. Какие-то сугубо математические свойства Curve25519, типа наличия кофактора и т.п., вовсе и не являются необычными – такие кривые вполне себе подходят и для ECDSA. Так что, если нет доверия той же P-256, но нужен именно алгоритм ECDSA – можно взять Curve25519. Использование же Ed25519 в данном протоколе невозможно из-за особенностей преобразования ключей, о чём, собственно, сказано в RFC. Насчёт “более быстрого” алгоритма Ed25519 – это, в основном, определяется как раз параметрами кривой (поле и т.д.).
Что касается странного дополнения про 32-байтовый и 64-байтовый ключи: тут, наверное, что-то перепуталось на каком-то этапе пересказывания. В Ed25519 секретный ключ – 32-байтовый. И в ECDSA на P-256 (например) – тоже 32-байтовый. Потому что разрядность в 256 бит (32 байта) делает бессмысленным использование секретных ключей большей длины: всё равно значение сократится. А 64 байта – это общий размер подписи, а не ключа.
Можно предположить, что тут ещё сыграло следующее популярное заблуждение, которое нередко наблюдается в отношении SSH-ключей: многие считают, что, например, поскольку открытый ключ Ed25519 короче, чем ECDSA на той же P-256, он поэтому и менее “криптостойкий”. Действительно, для ECDSA/P-256 открытый ключ обычно записывается в 64 байта (иногда чуть меньше, иногда – чуть больше, зависит от кодирования), а в Ed25519 – только в половину, в 32 байта. Однако эти 64 байта ECDSA математически эквивалентны 32 байтам, там половина байтов приносит только один бит дополнительно: открытый ключ представляет собой точку на кривой, у точки – две координаты (X,Y), каждая по 32 байта, и вот полная форма записи ключа ECDSA подразумевает указание объединения X и Y, откуда и получается 64 байта; однако можно указывать только одну координату (X), а вторую (Y) – вычислять из уравнения кривой при необходимости. В такой схеме, для ECDSA, потребуется сохранить дополнительно знак, это один бит, и получается тоже около 32 байтов для записи открытого ключа. А вот в Ed25519 алгоритм предписывает всегда использовать только одну координату (ну, строго говоря, там есть ещё некоторые преобразования, но здесь они не важны). То есть, математически эти ключи совпадают по представлению, отличие тут чисто прикладное, поэтому дополнительные 32 байта записи для ECDSA не делают даже открытый ключ в два раза длиннее “криптографически” – он всё равно 256-битный (по разрядности кривой).
Комментировать »
Надо сказать, я несколько лет назад отмечал, что интересно будет посмотреть, внедрит ли Google поддержку ESNI в свой браузер. Интерес, на мой взгляд, тут происходил из того, что Google последовательно отказывался поддерживать такие технологии обеспечения безопасности, которые использовали тот или иной независимый инструмент управления криптографическими ключами в TLS. Примеров два: изгнание из веба DANE (отпечатки ключей/сертификатов в DNS, для сверки с предъявляемыми сервером) под предлогом замены на Certificate Transparency (которая хоть и полезная, но о другом, так как не может предотвратить использование валидного подменного сертификата в момент соединения); отключение HPKP (запоминание отпечатков серверных ключей клиентом, как в SSH).
И вот я предположил, что, вероятно, ESNI тоже не будет в Google Chrome. Но сейчас вышло иначе: вместо исходного варианта ESNI – Google Chrome (Chromium) всё же поддержал ECH, а это развитие ESNI, гораздо более продвинутое. Впрочем, думаю, что в этой “продвинутости” и состоит причина поддержки: всё же, ECH далеко ушла от первоначальной идеи ESNI – позволяет реализовать доступ к скрытым сервисам, при этом наследует доверие системе хорошо известных удостоверяющих центров (“имени CA/B-форума”); впрочем, ECH и ключи для дополнительной защиты внутри TLS позволяет публиковать, например, в DNS, то есть, не централизованным способом, который, формально, не зависит от браузера (но нельзя забывать о встроенной поддержке DNS-over-HTTPS с заданными провайдерами). В общем, поддержка внешних ключей появилась, но теперь нужно посмотреть, как будет она развиваться: ведь доверенные ключи для ECH могут приезжать и вместе с браузером – это важная особенность.
Комментарии (2) »
В продолжение записки про наложенные сети Google для браузера. Внедрение таких перемешивающих технологий, конечно, заметно изменит ландшафт для систем фильтрации и блокирования (с DPI), которые будут внешними (относительно google-сетей). Внутри, понятно, возникнут своя фильтрация и блокирование, в точном соответствии с концепцией “Битвы за банхаммер“. Но снаружи останутся видны только IP-адрес клиента и IP-адрес входного узла Google – это важный момент: адрес не какого-то HTTPS-сервера или прокси, а сервиса доступа к вебу от Google. При этом протокол доступа у всех клиентов будет одинаковый.
Браузеры очень распространены, это один из основных источников трафика обычных пользователей – если привычный браузер перестанет работать “из коробки”, то, для таких пользователей, это окажется эквивалентно исчезновению доступа к Интернету. Однако, чтобы использовать наложенную сеть, программа-клиент не обязательно должна быть браузером: механизм доступа конкретно к браузеру не привязан – там достаточно универсальное туннелирование. Впрочем, похоже, что будет требоваться Google-аккаунт и аутентификация при доступе, но этот момент тоже переносится в другие приложения.
И занятно будет посмотреть, кстати, с какими эффектами работа наложенной сети, в ходе развития технологии, переедет в браузеры, которые базируются на Chromium/Chrome, но считаются как бы обособленными и самостоятельными.
Комментировать »
В атаке с перехватом трафика Jabber.ru использовался активный сетевой прокси с MITM. Однако если процесс, реализующий TLS, исполняется в виртуальной машине, а гипервизор контролируется провайдером хостинга, то можно проводить полностью пассивную атаку с рашифрованием TLS-трафика, да так, что из виртуальной машины атаку видно не будет. Это существенно сложнее прокси, терминирующего TLS с подменным сертификатом, и ограничивает возможности по расширению атаки до активной (с вмешательством в трафик), но является куда как более изящным методом. Для реализации требуется доступ к функции копирования (“дампа”) памяти гипервизора, а кроме того, естественно, доступ к сетевому трафику виртуальной машины (либо тоже на уровне “виртуализации” гипервизора, либо на уровне “внешней” сети).
Основная идея такая: общий сессионный секрет и сеансовые ключи TLS-соединения находятся в оперативной памяти виртуальной машины – нужно их из памяти извлечь, выполнив выгрузку копии памяти гипервизором в подходящий момент. Самое занятное, что это же относится и к секретному серверному ключу сертификата, который, впрочем, во многих случаях ещё и просто лежит в статическом файле на диске, в открытом виде. Извлечение и использование серверного ключа из файловой системы, при доступе к гипервизору, вообще представляет тривиальную задачу и тут не рассматривается. Варианты с зашифрованным файлом, с зашифрованным томом (диском) – уже сложнее, но тоже реализуемы; так или иначе – это не относится к анализу TLS. А вот извлечение разнообразных ключей из дампа оперативной памяти – относится, поэтому рассмотрим метод в общих чертах, за вычетом возможных мер по маскированию ключей в памяти (см. ниже).
В TLS набор симметричных сеансовых ключей используется сторонами для зашифрования/расшифрования и вычисления кодов аутентификации, поэтому знание ключей позволяет расшифровать TLS-сообщения и подделать TLS-сообщения. Для получения действующих сеансовых ключей используется некоторый общий сессионный секрет, согласованный в начале TLS-сессии. Этот секрет позволяет простым способом вычислить сами сеансовые ключи (обратное – не верно), поэтому достаточно найти сессионный секрет. В TLS 1.3 процесс работы с исходными секретами разбит на шаги, каждый из которых выводит симметричные ключи для соответствующего этапа соединения, так что ситуация несколько сложнее, но эти детали тоже пропустим.
Чтобы зафиксировать нужные симметричные ключи в памяти виртуальной машины, нужно определить момент, когда они там образуются. Если момент упустить, то сеансовые ключи могут быстро потеряться, так как соответствующие байты в памяти окажутся перезаписаны. Для фиксирования удобного момента требуется наблюдение над сетевым трафиком: по статусу TLS-соединения можно определить, что приложение должно вычислить ключи, и в этот момент сделать дамп памяти (или несколько последовательных дампов). Ход сетевого трафика, при необходимости, можно и “подвесить”, так как речь всё же идёт про ситуацию контроля над гипервизором. После того, как дамп памяти снят, данные из него анализируются с целью извлечения ключей, а TLS-трафик пассивно записывается.
Как найти ключи в дампе памяти? Есть прямой, но не самый быстрый, способ полного перебора: пробное расшифрование (или вычисление кода аутентификации) выполняется по порядку для каждой байтовой последовательности дампа нужной длины. Возможны, конечно, варианты, когда значение ключа оказалось в дампе памяти разрезано на части, поэтому такой перебор не сработает. Более точные результаты даст предварительная разметка областей по признаку записи, а также анализ логических блоков по схеме представления памяти в гостевой ОС. Понятно, что это всё можно сделать на уровне гипервизора. Для чего-то даже имеются готовые инструменты, что-то придётся запрограммировать. Схема с перебором работает и для секретного серверного ключа, только вместо пробного расшифрования нужно выполнять другую операцию (например, для ECDSA – пробное умножение; но это детали, главное, что в TLS-трафике всегда есть опорные метки).
Ключи и секрет могут быть замаскированы в памяти приложением (обычно, XOR с псевдослучайной маской, маска хранится отдельно или вычисляется по необходимости специальной функцией). Такое решение встречается нередко. Однако для того, чтобы ключи использовать – их всё же придётся раскрыть для операций хеш-функций и шифров, поэтому достаточно угадать момент выполнения дампа памяти. (Можно предложить алгоритмы с дополнительным непрерывным перемешиванием адресации и масок на уровне реализации шифров/хеш-функций, но вряд ли такое где-то встречается на практике.)
Проблемы с данным методом могут начаться тогда, когда параллельных TLS-соединений очень много: с одной стороны, возрастают шансы поймать много ключей в дампах памяти, с другой – дополнительные сложности с отслеживанием и сопоставлением состояний.
Перевод атаки в активную возможен, если не возникло существенного рассогласования по времени между моментом определения ключей и TLS-сессией. Так как атакующей стороне известны секретные симметричные ключи, она может подготовить корректную TLS-запись (или несколько записей) с нужными данными и встроить их в трафик, перехватив какие-то элементы протокола, работающего внутри TLS – но тут необходимо учитывать, что разойдутся счётчики и последовательность записей, так что подлинная сессия, вообще говоря, развалится, однако можно её до какой-то степени продолжать подменным узлом.
Схема работает не только для TLS, но и для других протоколов (SSH, например), если только реализации не подразумевают достаточно сложных механизмов защиты ключей. При этом понятно, что никакой “полной защиты” от гипервизора тут быть не может.
Комментарии (3) »
В свете нашумевшей атаки на Jabber.ru (с перехватом TLS) нередко пишут, будто эта атака показала, что “система хорошо известных (публичных) удостоверяющих центров TLS не вызывает доверия”. Атака, конечно, такое показала, но с уточнениями: “система хорошо известных УЦ” и раньше должна бы “вызывать доверие” равно в пределах разумной модели угроз, то есть – доверять ей можно только в сугубо определённых, узких случаях. И нельзя расширительно толковать возможности УЦ – это как раз большая ошибка, но весьма распространённая. В случае же инцидента с Jabber.ru, если говорить о сторонах, которые “вызывают доверие”, то тут такой стороной должен быть прежде всего хостер – предполагается высокая степень доверия хостеру (но не полное доверие, даже в этом случае), а только потом – немного доверия УЦ.
Комментарии (4) »
Представьте, что некоторый протокол туннелирования в Интернете устроен следующим образом: в качестве базового транспорта используется UDP (то есть, отсутствуют сессии транспортного уровня, тут это важно); применена схема “клиент-сервер”, использующая двухстороннюю аутентификацию с общим секретом, а процесс аутентификации тоже полностью зашифрован (пробное расшифрование и т.д.); используются различные IP для серверов – точек входа, а также динамически изменяемые номера портов; полезные данные тоже полностью зашифрованы – отсутствуют какие-либо открытые заголовки (кроме UDP), отсутствует фиксированная структура пакета, пакеты имеют разную длину, а адреса/номера портов изменяются в ходе соединения. Подобные протоколы есть, но в этой заметке речь о том, почему именно такой подход создаёт трудности в обнаружении и блокировании соединений.
Протокол медленный, не предназначен для создания стабильных и широких каналов, но зато он скрытый, полностью “мутирующий” и “размытый” (возможно, кто-то из читателей помнит, как в своё время появились первые развитые “полиморфные” компьютерные вирусы, содержавшие зашифрованное тело и генерируемый псевдослучайным образом “распаковщик” – теоретически, никаких статических сигнатур). Описанный протокол как раз внешне выглядит как случайный поток случайных UDP-пакетов, в котором не видно никаких сессий и контекста, не определяется внутренний статус, а общим является только адрес возможного клиента, так как он фигурирует и в отправителях, и в получателях, а вот уже входной и выходной серверные IP-адреса могут изменяться; это особенно занятно, если использовать IPv6 (за скобками оставлено преодоление NAT и некоторые другие сетевые особенности).
Теперь представьте, что некоторая система DPI должна блокировать соединения и прерывать сессии, используя в качестве флага тип протокола. Но у “размытого” протокола, описанного в предыдущем абзаце, нет устойчивых признаков, позволяющих уверенно определить его тип. Конечно, можно сказать, что такой признак всё же есть, просто он “несобственный” – исследуемый протокол “не похож ни на что известное”. Но для такого метода классификации нужно не только составить “белый список” протоколов, но ещё и так запрограммировать систему, чтобы она и классифицировала все протоколы, а это исключает всякую гибкость в пропуске трафика. Скажем, вот обнаружен UDP-пакет, который пока что не соответствует никакому контексту из уже созданных узлом DPI, инспектирующим трафик: если пакет относится к этапу установления соединения в рамках “размытого” протокола и если этот пакет не пропустить, то такое соединение не состоится. Но как определить, что это не пакет, выпавший из другой сессии “разрешённого” протокола (типа DTLS, предположим)?
Надёжное определение контекста становится затруднительным на достаточных объёмах трафика: у допустимых протоколов есть внутренние открытые заголовки, но они короткие и, в теории, могли просто совпасть, поэтому обязательно нужно взвешивать дополнительные параметры по нескольким пакетам – длину, адреса, номера портов. Но чтобы взвешивать несколько пакетов, для них придётся создать некоторую очередь измерений. А как сделать такую очередь эффективной, если туда предлагается складывать всё, что не получилось разобрать? Кроме того, задержка пакета “размытого” протокола приводит к тому, что другие пакеты просто не поступают – не из чего собирать полезный контекст в принципе. Если один “размытый” пакет пропустить, то получится, что и обмен данными случился, и тут уже вовсе не обязательно, что пакет относился к процессу аутентификации – он мог и нести полезные данные в рамках скрытой сессии. Более того, если некоторые пакеты проходят, то это означает, что сам “размытый” протокол успешно работает, преодолевая блокирующие узлы, потому что одно из заявленных свойств протокола – его внутренний статус нельзя определить даже по нескольким пакетам.
Вообще, классификация подобных протоколов с формированием контекста с целью распознавания – та ещё задача. В упрощённом виде можно представить, что классификатор работает с некоторым деревом состояний, переходы по которому определяются наличием видимой для DPI активной сессии между узлами (то, что в распространённых брандмауэрах называется Established connection), наличием ответных (парных) сообщений (это детектирование типовых “хендшейков” вида “запрос-ответ-подтверждение” на начальной стадии), соответствием заголовков транспортных пакетов и параметров адресации (адреса, номера портов), наличием заданных сигнатур и средним объёмом переданных данных. Понятно, что только лишь поиск сигнатур в конкретном пакете – тут заведомо не работает: нужно именно сопровождение состояний во времени. При этом классификация пакетов “размытого” протокола требует максимального задействования вычислительных ресурсов, нужных для расчёта эволюции только что описанного дерева – ведь каждый пакет требуется обработать, провести по функциям проверки, а потом положить информацию в буфер, чтобы позже проверить, не придёт ли какой-то ещё пакет, который можно привязать к уже полученному. Так что это всё скорее теоретические рассуждения, чем доступные на практике методы.
(Я уже писал о полностью зашифрованных протоколах раньше, в том числе, про распределение ключей и влияние TLS.)
Комментарии (3) »
Почему “спагеттизация” Интернета не относится напрямую к технологиям создания, собственно, “каналов связи”? В принципе, на уровне от “физического порта” до “физического порта” сейчас тоже присутствует виртуализация, а создание туннелей под собирательным названием “L2VPN/MPLS” – вполне себе распространённая практика. То есть, трафик и на этом уровне может ходить замысловатыми путями, тут имеется собственная маршрутизация, хитрая динамическая коммутация и прочие занимательные инструменты. Это так, однако Интернет – это IP плюс автономные системы с BGP (и плюс DNS, конечно), а также более или менее непрерывная, в смысле IP/BGP, “глобальность” (которая пока что ещё остаётся доступной на практике). “Глобальность” важна потому, что IP-сети повсеместно используются и вполне себе изолированные. Но, конечно, элементы “битвы за банхаммер” наблюдаются и на уровне “отключения канала и портов доступа”.
Комментировать »
В продолжение предыдущей записки о том, что Google успешно строит наложенную сеть для защищенного доступа своего браузера к веб-ресурсам. Интересно, что у Google информация о том, какие ресурсы посещал пользователь браузера, естественным образом сохраняется, поскольку для доступа к сети потребуется google-аккаунт. Не обязательно, чтобы историю прямо выдавал только браузер – собирать данные можно и при помощи веб-счётчиков Google Analytics, которые установлены едва ли не повсеместно.
Другой занимательный аспект: может даже так получится (из-за блокирования точек входа и отдельных веб-ресурсов в национальных сегментах, например), что для доступа к более или менее “глобальному” вебу потребуется аккаунт Google.
А кроме того, обычной может стать ситуация, когда на веб-сервис один и тот же пользователь в рамках одной и той же сессии приходит за разными ресурсами с различных IP-адресов (и все они относятся к точкам выхода из перемешивающей сети Chrome).
Комментировать »
Новый