Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
Пишут про перехват TLS-трафика сервиса Jabber.ru, без ведома администраторов: это практическая атака, судя по подробному описанию – там всё как положено: MITM в TLS и подмена серверного сертификата на тоже валидный. Как пишут, выпуск сертификата, скорее всего, проведён при помощи перехвата трафика, идущего на оригинальный сервер – подменные сертификаты попали в CT-логи, в описании есть на них ссылки (это сертификаты Let’s Encrypt, конечно).
Вообще, побороться с подобной подменой, когда возможен перехват трафика на уровне хостера (а это практически всегда так), весьма сложно. Единственный более или менее эффективный способ – прямая авторизация серверных ключей клиентом по отпечаткам, однако, это сложно, плохо масштабируется, ну и так далее. (Отмечу, что применительно к Jabber/XMPP – есть схемы с защитой точка-точка, между пользователями – OMEMO, например). Certificate Transparency (CT), CAA и подобные технологии, направленные на УЦ, от таких атак не особо защищают: CT, несомненно, полезно, но часто работает постфактум, потому что, как минимум, нужно клиентам проверять метки в сертификатах; и это, если вообще считать, что CT тут работает – технически, выпустить быстрый подменный сертификат УЦ может без меток логов, ничто этому не мешает; да и метки можно сделать без публикации в логах, если есть ключи от этих логов; но, конечно, это всё существенно усложняет процесс. Что касается CAA-записей: да, это полезно, но для УЦ, технически, отказаться от проверки CAA ещё проще, чем проигнорировать CT-логи и SCT-метки.
(Ссылка: описание инцидента от OpenNet на русском.)
Дополнение: понятно, что УЦ, в такой конфигурации атаки, ни при чём – УЦ не имеет возможности в рамках сетевых протоколов отличить подменный узел от настоящего с точностью, превышающей перенаправление сетевого трафика в локальной сети хостера; естественно, автоматически выпускаемые TLS-сертификаты для веба не могут служить инструментом защиты от подобных атак, это и не планировалось, никакие CT тут не помогут; возможность активного и полного перехвата трафика с подменой – автоматически приводит к возможности выпустить TLS-сертификат с соответствующим именем хоста через УЦ TLS; перехват трафика – позволяет подменить данные и при DNS-проверке, это даже в чём-то проще, но перехватывать нужно трафик к DNS-серверам и/или от них (и не должно быть поддержки DNSSEC, да).
Комментарии (4) »
Идея заменить простой, обозримый и понятный HTTP, построенный по схеме “запрос-ответ”, на вариант, инкапсулирующий часть логики TCP внутрь ещё одного, более сложного, протокола, с мультиплексированием и приоритизацией, который, тем не менее, сам работает внутри TCP-соединения, ожидаемо приводит к появлению новых, хитрых направлений DoS-атак, эффективно использующих “перемешивание логики” между этими вложенными протоколами. В данном случае – речь про HTTP/2: такую атаку и разбирают в блоге Cloudflare.
(Кстати, об особенностях мультиплексирования HTTP/2 регулярно забывают, что приводит к попыткам ограничить поток HTTP-запросов для проксирующего веб-сервера, который работает по HTTP/2, “силами iptables” по TCP-соединениям.)
Комментировать »
Anycast (в Интернете) – это, грубо говоря, способ распределить один IP-адрес на несколько узлов. Глобальный anycast подразумевает, что некоторый IP-адрес обозначает разные узлы, расположенные в совсем разных сетях и, возможно, разных регионах. Применяется данная технология, обычно, для того, чтобы сделать входные узлы некоторого глобального распределённого сервиса ближе к локальным пользователям, сохранив нумерацию в IP-адресах (“ближе” здесь обозначает расстояние в смысле сетевых маршрутов пакетов).
Есть занятный, пусть и не самый точный, способ определения того, что какой-то глобальный и маршрутизируемый IP-адрес соответствует anycast-узлу: нужно измерить время ответа (ICMP) при помощи утилиты ping, но сделать это из двух базовых точек, заведомо находящихся в существенно разных регионах, а потом измерить ping между этими точками. Если сумма для времени от точек измерения до измеряемого узла существенно меньше, чем время между базовыми точками, то, скорее всего, тут присутствует anycast. Это неравенство треугольника, и оно тут при помощи anycast нарушается.
Естественно, неравенство треугольника в интернет-сетях может нарушаться и по другим причинам. При этом, так сказать, “плотность” подобных нарушений, измеряемая на выборке узлов, может свидетельствовать о том, что где-то нужно поправить правила балансировки. А вообще, в современной глобальной Сети, из-за усиливающейся “спагеттизации“, подобная сетевая “измерительная геометрия” приобретает всё большее значение: когда трафик ходит через VPN, эффекты от anycast могут быть совсем не такими, как планировалось.
Комментировать »
Один из самых старых способов скрытого получения доверенного доступа к не менее скрытым сервисам в Интернете (как IP-сети) это port knocking (метод “секретного портового стука”). Суть метода изложить не трудно: скрываемый сервис работает на закреплённом за ним номером порта, но доступ для TCP-соединений (например) к этому номеру порта открывается только для тех IP-адресов, которые выполнили установленный набор попыток подключений по другим номерам портов. Чуть более развёрнутое объяснение для тех, кто не сетевой инженер (опять же, используем TCP): TCP-соединение – это соединение “точка-точка”, на каждом из концов соединению соответствует IP-адрес и номер порта, где номер порта, можно считать, это просто 16-битное число; например, 10.11.12.13:14395 -> 10.101.102.103:22 – соединение клиента с номером порта 14395 на серверный номер порта 22 (это обычный номер для SSH); предположим, что доступ на сервере по порту 22 закрыт межсетевым экраном (брандмауэром), то есть, попытка соединения на этот номер порта будет проигнорирована сервером; но если некоторый клиент с IP 10.11.12.13 выполнит попытки TCP-подключения на другие номера портов сервера по заданной ключевой последовательности: 1011, 1022, 1033, то брандмауэр, который фиксирует у себя попытки подключения, откроет подключения по номеру порта 22, но только для соответствующего IP-источника.
Естественно, все номера тут могут быть любыми (из допустимых интервалов). Метод весьма полезный, я его использую для открытия доступа к шлюзам, ведущим в некоторую “закрытую” сеть: совершенно необязательно открывать конкретный сервис на конкретном узле, с тем же успехом можно открыть туннель.
Почему-то данный метод и известен не столь широко, как можно подумать, да и нередко его необоснованно относят к способам защиты из разряда Security through obscurity (“Безопасность через неясность”, в одном из переводов), которые, как бы, “заведомо слабые”, что как раз и есть хороший пример неверного обобщения “принципа Керкгоффса”. Однако данный метод хорош, если используется по назначению и в верном контексте. А если излишне настойчиво обобщать, то и авторизация SSH по ключу может показаться “безопасностью через неясность” – действительно, а как если бы он знал значения байтов секретного ключа и их последовательность? Впрочем, это лирическое отступление.
Идея port knocking очень гибкая, потому что достаточно общая: во-первых, годится и TCP, и UDP, и ещё что угодно “с номерами”; во-вторых, последовательность “стука” не обязательно фиксированная – если есть общий секретный ключ и общее время, то номера можно генерировать псевдослучайным образом; в-третьих, вежливо постучать клиент может в один узел (IP-адрес), а доступ ему откроется на совсем другом (так тоже бывает). Поэтому именно “портовый стук” представляет собой эффективный дополнительный инструмент, затрудняющий обнаружение скрытого сервиса разными активными сканерами (что называется – connection probe). Если последовательность стуков неправильная, то, понятно, никто на неё просто не ответит, поэтому и никакой новой информации получить не выйдет.
Действительно, номера портов, которые открывают возможность соединения, видны в сетевом трафике. Но если это псевдослучайная последовательность, толку, в плане анализа трафика и сервисов, от этого не очень много – мало ли кто и какие порты сканирует? Добавление же контекста в DPI тут существенно повышает сложность анализа трафика. К port knocking можно добавить пакеты (UDP, например), содержащие дополнительные ключи, что, вместе с заменой адресов, совсем хорошо перемешает информацию, ещё больше затруднив анализ и построение контекста. Интересно, что через номера портов, в принципе, можно передавать и выбранный номер входного узла, к которому требуется получить доступ. То есть, конкретный вход в туннель и его свойства определяются выбранной последовательностью “стуков”. Впрочем, если простой port knocking в линуксах, например, относительно легко реализуется силами iptables (типовой межсетевой экран), то расширенные, хитрые способы – потребуют отдельного специализированного модуля, обрабатывающего низкоуровневую информацию о соединениях.
Комментарии (3) »
Кстати, в продолжение предыдущей заметки. В исходной работе (почему-то по оригинальной ссылке её больше нет, но, думаю, можно найти) в качестве примера используется модификация аппаратного генератора (датчика) случайных чисел, которая приводит к снижению эффективной энтропии до значений, доступных для быстрого прямого перебора. Что это означает и как может работать на практике, а не в качестве примера? Конечно, если бы речь шла о прямой замене на максимальное количество в 2^32 различных значений для 128-битной разрядности, то такой дефект элементарно обнаружился бы: он не только быстро проявится на статистике, но и будет выглядеть максимально подозрительно даже для самых простых методов – 2^32 16-байтных значений сейчас влезает в ОЗУ некоторых ноутбуков. Поэтому речь идёт о другой схеме. Практическая реализация должна работать в другом контексте: предполагается, что сторона, которой известно секретное значение, по нескольким результатам выдачи генератора (задающие элементы – их может быть даже два или три) за 2^32 (например) операций вычислит внутреннее состояние генератора и получит следующее значение, которое генератор выдал (ну или получит 116 битов из 128, а остальные – подберёт на следующем шаге). Во многих протоколах значение случайного числа, которое выдал генератор, передаётся в открытом виде, так что его можно прочитать тем или иным способом. А дальше уже, из-за свойств симметричных шифров и/или хеш-функций, можно найти точные ключи перебором. При этом в выдаче всегда остаётся некоторая добавленная энтропия, – предположим, аппаратная, – которая мешает вычислительно отличить выдачу генератора от качественной, если не известен ключ.
Комментировать »
Десять лет назад на dxdt.ru, например, появилась заметка про занятную реализацию аппаратных закладок. Цитата:
Преимущество метода в том, что созданные с его помощью троянские модификации микросхем практически невозможно обнаружить, “топологически” исследуя кристалл по слоям при помощи электронного микроскопа (или другого оборудования): не добавляется новых элементов, изменённые транзисторы на снимках выглядят так же, как и штатные. Более того, “троянская” схема успешно проходит процедуры контроля качества.
Комментировать »
Кстати, очередной раз про квантовую криптографию, реализации которой являются средством технической защиты информации, поэтому их нельзя сравнивать с математическим аппаратом криптографии, а тем более считать, что возможна некоторая абсолютная защита “физическими принципами”: “физические принципы” могут обеспечить прекрасную защиту в виде металлического контейнера для секретного симметричного ключа, но почему-то эту защиту, эквивалентную по основным рискам квантовой криптографии, не называют “абсолютной”. Собственно, почти семь лет назад я написал по этой теме довольно подробную записку, рекомендую: “Кванты, квантовая криптография с компьютерами“.
Комментировать »
Предполагается, что постквантовые криптосистемы – это защита от взлома на квантовом компьютере. На гипотетическом квантовом компьютере, который может реализовать соответствующие алгоритмы – алгоритм Шора, прежде всего. Конечно, современный уровень “хайпа” вокруг квантовых компьютеров уступает уровню “хайпа” вокруг “искусственного интеллекта”, тем не менее, квантовых компьютеров, подходящих для атак на используемые сейчас криптосистемы, ещё никто не показал. И даже ничего близко похожего – не показали. Но если почитать, например, статью про квантовые вычисления даже в англоязычной “Википедии”, то там почему-то уверенно обсуждаются “практические особенности”. Но до “практики” же ещё очень далеко. Пока что даже исследовательские алгоритмы, призванные показать “квантовое превосходство”, требуют создания специальных задач, которые структурно оптимизированы не в направлении вычислительной полезности, а в направлении использования свойств, потенциально доступных на имеющихся сейчас квантовых устройствах (см. boson sampling). Это естественно, весьма логично для этапа теоретических исследований на экспериментальном оборудовании, но не относится к практическому применению универсальных компьютеров.
В популярных изложениях нередко сильно искажают ситуацию (а иногда – искажают и не в совсем популярных: см. историю про “голографическую кротовую нору”), заявляя, что алгоритм Шора уже был успешно реализован на таких-то и таких-то конфигурациях. При этом для алгоритма Шора ключевое значение имеет не “суперпозиция состояний”, про которую всё время рассказывают, а реализация квантового преобразования Фурье, потому что именно в нём состоит содержательная часть – алгоритм должен работать потому, что схемы преобразования Фурье позволяют, в теории, определить период функции, заданной на значениях квантовых регистров. Однако в экспериментах именно эту часть (преобразование Фурье) существенно упрощают или вообще исключают, так как нет доступных экспериментальных квантовых схем, подходящих для практической реализации. На малых разрядностях (несколько битов/кубитов) преобразование Фурье для алгоритма Шора вообще не имеет вычислительного смысла, поскольку в принципе нельзя увидеть “длинных” периодов. Не исключено, что в случае “коррекции ошибок” на дополнительных схемах – преобразование Фурье совсем не будет работать для отыскания периода из-за того, что алгоритм-то, по предназначению, целочисленный. И это если оставить за скобками то, что создание гипотетического квантового компьютера большой разрядности напрямую затрагивает основания современной физики, поскольку именно такой квантовый компьютер с необходимостью попадает на границу между “квантовым (микро)миром” и “неквантовым (макро)миром”, которая совсем не ясна, вокруг которой строятся разные интерпретации.
Из этого, впрочем, не следует вывод, что квантовые компьютеры подходящей разрядности вообще не создадут. Но пока что трудности большие.
Комментарии (1) »
В продолжение недавней записки про X25519Kyber768 на TLS-сервере – подробности встраивания данной гибридной криптосистемы в схему работы TLS 1.3.
(Дополнение, 17/12/2024: в 2024 году Kyber768 была стандартизована NIST под обозначением ML-KEM; ML-KEM, как алгоритм, имеет некоторые отличия от Kyber768, поэтому две криптосистемы, хоть и совпадают по математической основе, но не совместимы на уровне операций. Браузеры, чтобы не поддерживать несколько максимально похожих криптосистем, использование которых сопряжено с передачей больших блоков данных, перешли с Kyber768 на ML-KEM, но тоже в составе “гибрида” X25519 + ML-KEM. Способ встраивания ML-KEM логически полностью совпадает с описанным ниже для Kyber768, отличается только порядок блоков данных.)
1. Как нетрудно догадаться, X25519Kyber768 состоит из X25519 и Kyber768, поэтому криптосистема и гибридная. X25519 – это хорошо известный вариант протокола Диффи-Хеллмана (DH), здесь используется без изменений, обычным образом (см. кстати, заметку с задачей про 2^255 – 19). Kyber768 – схема KEM (инкапсуляции ключа), построенная на криптосистеме Kyber с “постквантовой стойкостью”. Эта криптосистема реализует зашифрование с открытым ключом (важный момент).
2. В TLS рассматриваемая криптосистема используется для получения симметричного сеансового секрета. Открытый ключ передаётся клиентом в составе ClientHello, в расширении key_share, а ответная часть сервером – в ServerHello, key_share. В логике сообщений тут ничего не меняется.
3. Изменяется часть внутри key_share, соответствующая X25519Kyber768 – клиент передаёт результат конкатенации байтов, составляющих клиентскую часть DH X25519 и открытый ключ клиента Kyber768. Эти данные имеют фиксированную длину, определяемую алгоритмами: 32 начальных байта для X25519 и 1184 для Kyber768, 1216 байтов всего. На сервере данные разделяются (просто, по длине) и используются для обеих криптосистем. А именно: для X25519 сервер вычисляет общий секрет DH и серверную открытую часть DH (B), так же, как это делалось бы в случае отдельной криптосистемы X25519; для Kyber768 – сервер генерирует общий секрет и оборачивает его в KEM (то есть, зашифровывает исходное секретное значение, используя открытый ключ Kyber, присланный клиентом – тем самые 1184 байта). Два секрета сервер объединяет в один массив – здесь, опять же, простая конкатенация: BaseSecret = x25519[] + Kyber_Shared_Secret[]. Обратите внимание на важное техническое отличие: для X25519 общий секрет, на сервере, это результат умножения открытой части DH клиента (A) на секретный скаляр сервера d: s = d*A; а для Kyber – сервер выбирает исходное значение, которое отправляет клиенту в зашифрованном виде (очень похоже на устаревшую схему с RSA-шифрованием в TLS, но устроенную наоборот). При этом внутри KEM Kyber для вычисления секрета по исходному значению используется отдельная функция (KDF), подмешивающая ещё и значение открытого ключа, это необходимый шаг, но, с точки зрения логики получения секрета, это не так важно. Секрет, генерируемый в рамках Kyber768 в TLS – это тоже 32 байта (256 бит). После завершения данного этапа – сервер получил общий симметричный секрет, представляющий собой объединение выдачи двух алгоритмов: 32 байта и 32 байта. Также сервер получил открытую часть DH и зашифрованный Kyber симметричный секрет (это только часть, предназначенная для Kyber, результат X25519 сюда не попадает).
4. Сервер формирует ответное расширение key_share, присоединяя к 32 байтам открытой части DH X25519 байты шифротекста с симметричным секретом, который зашифрован Kyber – длина шифротекста 1088 байтов, всего 1120 байтов. Ответное key_share сервер отправляет клиенту в открытой части сообщений, в ServerHello, после чего генерирует на основе общего секрета набор симметричных сессионных ключей и переходит к зашифрованному обмену данными.
5. Клиент, получив key_share X25519Kyber768, разделяет данные на открытую часть обмена DH X25519 (B) и шифротекст Kyber768. По значению B DH клиент вычисляет общий секрет DH X25519 (здесь – 32 байта), который совпадает с серверным. Используя секретный ключ, клиент расшифровывает шифротекст и вычисляет общий секрет Kyber. Оба полученных значения объединяются, результат должен совпасть с серверным. (Тут слово “должен” использовано потому, что в Kyber, к сожалению, есть вероятностный элемент: так как это схема, концептуально происходящая из кодов с коррекцией ошибок, то имеется очень небольшая вероятность, что “ошибка” всё же останется, а клиент и сервер получат разные значения секрета.) На основе объединённого секрета клиент вычисляет набор симметричных ключей и может проверить подлинность и расшифровать следующие сообщения сервера.
Таким образом, Kyber простым и понятным способом добавляет 256 бит “постквантовой стойкости” к исходному симметричному секрету TLS-сессии, какие-то другие параметры – не изменяются.
Комментировать »
Всё же я пока восстановил свой экспериментальный сервер TLS 1.3 – tls13.1d.pw (некоторое время назад я писал, что собираюсь его совсем отключить). А чтобы восстановление выглядело поинтереснее, я реализовал на сервере поддержку постквантовой схемы получения общего секрета (KEM) X25519Kyber768. TLS с Kyber768 там реализован вручную, но я, впрочем, использовал криптопримитивы из удобной библиотеки Cloudflare.
Криптосистему с постквантовой схемой KEM Kyber768 в конце августа Google внедрил в браузер Chrome (в порядке эксперимента), так что можете проверить – на сервере у X25519Kyber768 повышен приоритет, поэтому, при наличии соответствующего открытого ключа в сообщении клиента, выбираться она должна довольно часто.
Вообще, открытый блок клиентского KeyShare в X25519Kyber768 весит аж 1216 байтов (32 + 1184, потому что это ключ X25519, 32 байта, плюс ключ постквантовой части Kyber768, который большой). Тем не менее, я всё же пока что сделал вывод этого ключа без сокращений, что, возможно, выглядит тяжеловато, но видно будет только в браузере с поддержкой данной криптосистемы. (Дополнение, 12/09/2023: технические подробности об использовании криптосистемы.)
Поддержка есть только в самых свежих версиях Chrome (>=116), а включать её нужно через флаги: chrome://flags, набрать “TLS13” в поиске, флаг называется “TLS 1.3 hybridized Kyber support”.

(Не знаю, будет ли у меня возможность поддерживать сервер далее, так что в какой-то момент он может отключиться, теперь уже даже и без предупреждения, но посмотрим; ошибки подключения, естественно, могут быть и по другим причинам – это, всё ж, экспериментальный сервер.)
Комментировать »
Обычно, DNS-резолвер должен работать внутри VPN-сервиса – то есть, это может быть буквально обособленный резолвер, используемый именно в составе VPN (желательно, с DNSSEC). Но так делается далеко не всегда. Напомню, что DNS-резолвер (в данном случае, речь про рекурсивный резолвер) – это сервис, который проводит опрос серверов DNS, отыскивая, например, IP-адреса по именам узлов – адрес, по которому нужно браузеру обращаться к веб-серверу под именем test.ru. Резолвер выполняет то, что называется рекурсивным опросом: обращается к авторитативным DNS-серверам разных уровней. Эти серверы видят IP-адрес резолвера, но не клиента резолвера, который (вероятно) будет подключаться к сервису по обнаруженному в DNS адресу. При этом, для целей балансировки нагрузки на “целевой” сервис, DNS-серверу удобно было бы знать что-то о клиенте, для которого работает конкретный резолвер – потому что балансировка выполняется именно для клиента сервиса, а не для клиента DNS (сервис доменных имён (DNS) в этот момент уже на нужной стороне отработал). Это особенно актуально для больших открытых сервисов DNS-резолверов, например, Google Public DNS, так как эти сервисы обслуживают клиентов из самых разных точек сети. Чтобы как-то помочь оптимизации, довольно давно придумали расширение DNS под названием EDNS Client Subnet (ECS).
Данная технология (ECS) позволяет резолверу передать в сторону авторитативного сервера сведения об IP-подсети клиента, который обратился с запросом. Проще говоря – авторитативный сервер увидит IP-адресный блок, который соответствует клиенту, находящемуся за резолвером, что позволит определить провайдера. ECS как раз поддерживается Google Public DNS (и не только). Предполагается, что авторитативный сервер, определив провайдера клиента резолвера, сможет применить какие-то правила оптимизации. Если VPN используется для сокрытия IP-адреса пользовательского подключения, но DNS-трафик направляется не через VPN в какой-то DNS-сервис, то наличие ECS в этом сервисе (при прочих равных) означает, что внешние авторитативные DNS-серверы увидят скрываемую подсеть. Об этом нередко забывают.
Технический пример (не учитывающий NAT и другие тонкие настройки): предположим, клиентское устройство использует провайдерский доступ с адресом 10.11.12.13, ему соответствует подсеть 10.11.12.0/24; выход из VPN использует подключение с IP 10.22.22.22 (подсеть 10.22.22.0/24); DNS-трафик направляется напрямую (не через VPN) резолверу 10.53.53.53, резолвер поддерживает ECS. Тогда, при попытке определить значение A-записи (адрес), внешние серверы DNS узнают, что к ним подключается резолвер с адресом 10.53.53.53 для клиента из подсети 10.11.12.0/24. А вот на веб-сервере, к которому обращение произойдёт через VPN, адрес клиента будет виден как 10.22.22.22 – внешняя точка VPN. Естественно, если DNS-трафик маршрутизируется устройством через VPN, то внешний DNS-сервис с ECS сможет передать наружу только подсеть точки выхода VPN (10.22.22.0/24), поскольку именно адрес из этой подсети он видит в качестве источника запроса. Но лучше, конечно, если вообще используется собственный резолвер без ECS в составе VPN-сервиса, потому что возможны и другие каналы утечки метаинформации.
Комментировать »
Новый