Ресурсы: техническое описание TLS, LaTeX - в картинки (img), криптографическая библиотека Arduino, шифр "Кузнечик" на ассемблере AMD64/AVX и ARM64
Записка про процесс валидации TLS-сертификатов, сопоставления сертификата с TLS-узлом и аутентификации этого узла; всё – на примере TLS для веба (то есть, “HTTPS в браузерах”).
Валидация – это проверка и подтверждение того, что сертификат действует, соответствует сценарию использования ключа и подписан доверенным Удостоверяющим Центром (УЦ или CA в английском варианте). Аутентификация, в данном случае, состоит в проверке соответствия имён (в сертификате и в параметрах соединения) и получении подтверждения, что аутентифицируемый узел имеет доступ к секретному ключу, соответствующему открытому ключу из сертификата.
В самом первом приближении, процесс может быть описан весьма просто, однако внутри есть большое количество важных деталей. Некоторые из этих деталей рассмотрены в данной записке. В качестве примера здесь используется типичный сценарий работы с веб-сайтом по HTTPS: то есть, современный веб-браузер в качестве клиента, а современный веб-сервер – в качестве, как нетрудно угадать, сервера.
Для описания процесса, прежде всего, важны три типа сертификатов:
1) сертификат доверенного УЦ; обычно, это самоподписанный сертификат (см. ниже), который содержит открытый ключ корневого доверенного УЦ, список таких сертификатов входит либо в дистрибутив браузера, либо в дистрибутив операционной системы;
2) сертификат промежуточного УЦ; это как раз пункт, который традиционно является источником многих хитрых деталей; промежуточный УЦ возникает потому, что непосредственно от корневых ключей “обычные” (оконечные) сертификаты сейчас на практике не выпускают, а выпускают сертификаты промежуточных УЦ – секретные ключи, соответствующие открытым ключам из этих сертификатов, служат для подписи оконечных сертификатов, которые описаны в следующем пункте;
3) оконечный, серверный сертификат – это сертификат, который является, так сказать, целью проверки; он выпущен для сетевого имени, соответствующего параметрам (контексту) соединения, а секретный ключ, соответствующий открытому, должен быть известен серверу (либо должен быть доступ к операциям с этим ключом); именно оконечный сертификат непосредственно используется при установлении соединения для аутентификации сервера клиентом (бывают ещё клиентские оконечные сертификаты, схема валидации там такая же, но работает на стороне сервера; здесь случай клиентского сертификата не рассматриваем).
В ходе валидации выстраивается так называемая “цепочка доверия”. Цепочка выстраивается при помощи проверки подписей на сертификатах, но не только. Эта цепочка – иерархия сертификатов, в которой они соединяются по соответствию имён и открытых ключей. В сертификатах есть поля Issuer/Subject. Issuer – “Издатель”, название того УЦ, который этот сертификат выпустил. Subject – “Субъект”, название, к которому этот сертификат привязывает опубликованный в нём открытый ключ при помощи подписи от ключа Issuer (“Издателя”).
Например, для dxdt.ru цепочка может быть такой (здесь корневой сертификат – слева, ISRG Root X1, а “доверие” распространяется справа налево): ISRG Root X1 — R3 — dxdt.ru. Открытые ключи привязываются в этой цепочке к именам при помощи проверки подписей. Если проверка удалась, то ключ – верный. Ключи и имена обычно используются парой (в принципе, в списке может оказаться несколько одинаковых имён с разными ключами, хоть так быть и не должно, – в таком случае, приоритет будет у значения ключа).
Для корневого УЦ сертификат является просто контейнером ключа, этот сертификат “самоподписанный” – то есть, подпись от того же ключа, открытое представление которого указано в сертификате, совпадающие значения Issuer и Subject. На других сертификатах подпись вычисляется от ключа, соответствующего другому сертификату (на него тоже указывает имя из Issuer).
Для всех сертификатов цепочки должно быть проверено время действия. В сертификате, в специальных полях, записаны метки времени, обозначающие два момента: когда сертификат начинает действовать и когда сертификат заканчивает действовать (это время GMT с точностью до секунд). Сертификат не должен приниматься за пределами указанного интервала: то есть, сертификат может не только истечь (закончился срок действия, обычное дело), но может ещё не начать действовать (а это весьма экзотический для веба случай).
Все сертификаты в цепочке содержат указания на то, как можно использовать ключи, указанные в этих сертификатах. Например, сертификаты УЦ содержат флаг, который обозначает, что (секретный) ключ может использоваться для подписывания других сертификатов и, например, для подписывания списков отзыва (см. ниже). Это всё помимо отдельного флага, обозначающего, что данный сертификат – сертификат УЦ. Использование ключа должно соответствовать схеме проверки – например, валидатор не должен принимать сертификат, подписанный от ключа, (доверенный) сертификат которого не содержит флага УЦ или флагов, разрешающих подписывание.
Оконечный сертификат сопоставляется по имени с именем узла, с которым браузер пытается установить соединение. Это часть процесса аутентификации узла, использующая сертификат существенным образом. Современные спецификации таковы, что тут учитывается не имя узла из поля Subject, как можно подумать. В TLS-сертификатах есть специальное расширение SAN (Subject Alternative Name), где могут быть перечислены дополнительные имена. Именно тут должно быть указано имя сервера. Например, dxdt.ru. Иначе, согласно спецификациям валидации для современного веба, которым следуют браузеры, сертификат будет невалидным для заданного имени (даже если имя указано в Subject).
Сертификаты могут быть отозваны до достижения ими срока окончания действия. Поэтому, в теории, для каждого сертификата в цепочке валидации должен быть проверен его статус (отозван или нет). В практике веба отзыв проверяется далеко не всегда. Есть два базовых способа проверки статуса сертификата – файл со списком серийных номеров отозванных сертификатов (CRL – Certificate Revocation List) и респондер протокола OCSP (Online Certificate Status Protocol); а есть специальные способы, поддерживаемые современными браузерами, например, Chrome/Chromium, и серверами. Специальные способы возникли потому, что всякое обращение к сервисам проверки статусов сертификатов раскрывает некоторую информацию о сессии браузера в сторону УЦ. Вести сервисы статуса непосредственно могут только либо сами УЦ, либо организации, которым УЦ прямо поручили реализацию такой функции, это связано с необходимым доверием, чтобы сертификаты не могли “отзывать” произвольные участники системы. Поэтому, при типовых схемах, УЦ будет узнавать о проверках статуса и видеть имена, к которым были обращения. Но можно предложить способы различного “проксирования” статусов сертификатов: сюда относятся “концентраторы” списков отзывов – пример: OneCRL, – записи “слепков” ответов OCSP – OCSP stapling, – и включение статичных списков отзыва в состав обновлений браузера (это, прежде всего, Chrome, но для важных сертификатов используют и другие браузеры, например, Firefox).
О том, где можно проверить статус сертификата, валидатор может узнаёт из состава сертификата. Адреса узлов, публикующих CRL (списки отзыва), адреса OCSP-респондеров – прямо указаны в специальных расширениях.
С отзывом сертификатов связаны два практических вывода: 1) отзыв сертификатов и корректное “оборачивание” его в необходимые сервисы – одна из больших проблем для всякого УЦ; 2) в современном вебе отзыв сертификатов сайтов, фактически, не работает (но эту неработоспособность уже несколько лет активно пытаются компенсировать внедрением сертификатов с коротким сроком действия).
Если все подписи цепочки сошлись, то, в результате успешной валидации, браузер получает доверенный открытый ключ сервера – этот ключ содержится в оконечном сертификате. Остаётся ещё один важнейший шаг аутентификации узла: нужно проверить, что узел, приславший валидный сертификат, имеет доступ к соответствующему секретному ключу. В современных версиях TLS это реализуется при помощи подписывания сервером сообщения, состав которого определяется клиентом (чтобы нельзя было подготовить заранее подписанное сообщение). Если клиент успешно проверил подпись, полученную от сервера, при помощи ключа из сертификата, то сервер считается аутентифицированным (соответствие имён проверено раньше).
Ссылка по теме: техническое описание TLS (где про сертификаты не так много, поскольку их техническое значение в TLS не очень велико, так как основное их значение – административное).
Комментировать »
Касательно свежей истории с обнаружением закладки/бэкдора (CVE-2024-3094) в пакете xz (liblzma), которая на системах с systemd/glibc, потенциально, протягивалась в sshd: понятно, что такого может быть ещё много в уже массово используемых библиотеках, но всё равно это весьма неплохая и практическая демонстрация того, что подобное удаётся быстро обнаружить силами сообщества. По этой теме я не так давно писал, что, во-первых, добавление закладок и прочего вредоносного кода – это совсем не какая-то особенность Open Source; во-вторых – доступность исходников связана с возможностями по добавлению и обнаружению вредоносного кода, но вовсе не так прямо, как часто говорят и пишут.
Комментировать »
В продолжение предыдущей записки. Различные “аппаратурные” атаки, типа разновидностей Spectre/Meltdown, которые преодолевают механизмы разграничения доступа современных процессоров, имеют интересную связь с концепцией “диагонализации”: то есть, такие атаки всегда возможны, если только процессор пытается оптимизировать использование вычислительных ресурсов достаточно сложным способом. Под “достаточно сложным” тут подразумевается наличие механизмов вида “предикторов” (упреждающего анализа потока команд), задействованных на уровне над “межпотоковым” взаимодействием.
Вообще, в x86 “префетчинг” (предварительное извлечение) кодов команд появился ещё в микропроцессоре 8086. Но тогда соответствующая схема считалась просто конвейером команд. Это был отдельный компонент, со своими регистрами и системой счётчиков, который асинхронно считывал коды команд с внешней шины, когда та была свободна, что существенно ускоряло работу процессора. Понятно, что в 8086 не было ни каких-то особых механизмов аппаратного разграничения потоков команд и адресного пространства, ни обособленных полноценных ядер, исполняющих код, так что и проблем с побочными эффектами от работы схем конвейера тоже быть ещё не могло. Однако состояние этого конвейера, вмещавшего всего несколько кодов (четыре 8-битных регистра), изменяло состояние процессора вне зависимости от исполняемой основным “протоядром” команды, поскольку конвейер содержал пару указателей, несколько флагов и т.д. Впрочем, технические детали устройства исторического микропроцессора тут не важны – важно, что, во-первых, этот простой конвейер работал только на уровне последовательности кодов команд (не со свойствами самих команд); во-вторых, не было потоков и общих элементов, совместно используемых этими потоками.
Отличие “уязвимых” схем современных процессоров в том, что здесь добавляется новый уровень – те самые “предикторы”, оснащённые логикой, которая учитывает уже не порядок кодов команд, а свойства этих команд и состояние процессора, а кроме того, добавляются общие для нескольких потоков элементы (схемы кэширования и пр.) на работу которых прямо влияют предикторы. И, конечно, возникает аппаратное разграничение доступа, которое и предлагается преодолевать при помощи атак, использующих аппаратные уязвимости.
Базовая логика таких атак – использование “оракулов”, сигналы которых пробивают границы, устанавливаемые (формально) аппаратной архитектурой процессора для фрагментов программного кода. Тут нужно учитывать, что границы эти только декларируются, а в реальности – сигналы через них проходят (иначе тут не было бы предмета), потому что процессору необходимо оптимизировать исполнение кода и доступ к памяти. Эти сигналы обязательно будут возникать именно потому, что в процессоре появился уровень, исполняющий “программу над программой”: упреждающий анализ команд работает по собственной программе (пусть и записанной непосредственно в аппаратуре); эта программа не только использует все потоки и фрагменты кода в качестве входных данных, но и влияет на состояние общих для изолируемых фрагментов кода элементов (кэш и очереди команд). То есть, схема аппаратной оптимизации тут всегда будет сквозной, можно сказать, что неустранимой. Вопрос в том, нужно ли считать такую архитектурную черту уязвимостью. Получается, что общая программа смотрит на команды в разных потоках и переключает состояние общих элементов, чтобы оптимизировать процесс. Изолируемые процессы находят способ измерения времени переключения состояний и – строится очередная уязвимость.
Если попробовать бороться с возникающими по описанным только что принципам сигналами, но попытаться сохранять общие элементы процессора, то каждый новый слой просто будет приводить к появлению более хитрых способов измерения: многими “атакующими” потоками, по накопленной статистике, ещё как-то. Если в архитектуру процессора, предположим, введут некоторое зашумление переключений кеша и предикторов, то носителем сигнала окажется схема, реализующая зашумление. Всякое подобное усложнение, добавление новых уровней, приводит к тому, что появляются и носители новых сигналов (это и есть “диагонализация”). При этом защита от “уязвимостей” программными методами, снижающими общее быстродействие, выглядит несколько странно, потому что предлагается прилагать дополнительные усилия для создания затруднений в работе оптимизирующих схем, которые и в процессоре уже встроены (то есть, потрачена площадь подложки и элементарные логические узлы), и само ПО при этом всё равно работает на общей аппаратуре.
Радикальное решение предполагает либо полную и точную аппаратную изоляцию уровней и ядер, когда все компоненты продублированы и работают независимо, либо полную замену системы команд (не стоит списывать со счетов, что в x86 уже и некоторые отдельные команды обладают тьюринг-полной реализацией). Однако это противоречит самой идее аппаратурной оптимизации на границе между логическим представлением команд процессора и машинным микрокодом. Да и приведёт внедрение таких методов только к тому, что очередной “пробой изоляции” между потоками выявят на стороне шин и контроллеров, взаимодействующих с ОЗУ и периферийными устройствами.
Комментировать »
Почему-то много где громко пишут, что “обнаружена критическая неустранимая уязвимость процессоров Apple M1, раскрывающая криптографические ключи”, при этом имеется в виду новая “брендированная” атака Gofetch. Вообще, если почитать исходную работу, то речь там об очередном аппаратном “оракуле”, который использует, – опять же, очередной, – оптимизирующий компонент процессора: DMP (Data Memory-dependent Prefetcher), направленный на опережающее извлечение данных из памяти на основе косвенных “указателей” – то есть, значений, которые процессор считает записью адреса данных. Это популярное направление. Очень давно известно, что всякий подобный упреждающий механизм исполнения команд или извлечения данных порождает как минимум два побочных канала утечек (по записи и по чтению).
Подход Gofetch использует измеримые локально отличия в обработке тех “указателей”, которые схемы DMP смогли интерпретировать как “полезные” (то есть, показывающие на подходящие для упреждающего извлечения области адресного пространства), и “указателей”, которые получили статус “недоступных”. Это, конечно, выглядит занятно. Но нужно всё же учитывать и прочие параметры. Так, для успешного вычисления секретных ключей, атака должна проводиться из соседнего процесса и требует прямых вызовов функций атакуемого ПО. То есть программа уже должна работать в той же системе, на том же процессоре, где исполняется и полностью программный атакуемый “криптопровайдер”. Более того, атака требует штатного взаимодействия атакующей программы с этим “криптопровайдером” в течение длительного времени (ну и чтобы никакой другой процесс не помешал). Сложно придумать сценарий, где такая конфигурация будет действительно “неустранимой”.
Комментировать »
В свежих версиях веб-сервера Nginx есть полезная (и довольно экзотическая) опция для настройки TLS: ssl_reject_handshake (on | off), о которой, оказывается, мало кто знает. Опция позволяет управлять прерыванием процесса установления TLS-соединения (“хендшейка”) на стороне сервера. С помощью “ssl_reject_handshake on;” можно отклонить TLS-соединение, если в клиентском ClientHello указано имя хоста (поле SNI), которого нет на стороне сервера.
Почему это удобно. Штатная работа веб-сервера по HTTPS подразумевает, что при установлении TLS-соединения клиент передаёт имя хоста, соответствующее DNS-имени веб-узла; например, для https://test.ru/ это будет test.ru. Однако никто не запрещает клиенту обратиться с другим именем хоста в SNI. Более того, на тот же самый IP-адрес, который соответствует веб-узлу под именем test.ru, может быть направлено другое DNS-имя (другой домен). Веб-браузеры, обращающиеся по такому имени, будут указывать его в SNI, а сервер, при прочих равных, не сможет найти не только соответствующий “виртуальный хост” в конфигурации, но и подобрать корректный TLS-сертификат. Однако какой-то TLS-сертификат для установления TLS-соединения серверу нужен и, без дополнительных мер, это приводит к тому, что сервер отвечает с “первым попавшимся” (буквально) серверным TLS-сертификатом из сконфигурированных.
Если на сервере всего один виртуальный хост/веб-узел (или настроены отдельные IP-адреса для отдельных веб-узлов), то ничего нового клиент не узнаёт. Однако если виртуальных хостов много, то ответ с произвольным сертификатом приводит к нежелательным утечкам имён: клиент получит сертификат, в котором будет указано имя другого сервиса, доступного на этом же узле (или несколько имён). Администраторы и даже DevOps об этом постоянно забывают.
Сделать тут что-то корректное на уровне HTTP невозможно в принципе, так как TLS-соединение устанавливается раньше, а для каждого HTTP-ответа (403 и пр.) потребуется подходящий по имени доверенный сертификат. Да, возможны различные “костыли”, вроде использования заведомо несовпадающего сертификата-заглушки, но все они подразумевают некорректный ответ.
Указание “ssl_reject_handshake on;” для default_server (для имени хоста по умолчанию) позволяет побороть только что описанную проблему: Nginx будет прерывать именно TLS-соединение, если клиент обращается с неверным именем хоста в SNI – это, что называется, технически строгий способ. Браузер, в таком случае, выведет сообщение о недоступности узла, а не предупреждение о несовпадении имён, которое пользователи привыкли преодолевать при помощи кнопки “Всё равно продолжить”.
Комментировать »
Современные компиляторы хорошо умеют оптимизировать машинный код и обычно делают это гораздо лучше разработчика. Но нужно учитывать тот факт, что программа на некотором языке высокого уровня (ЯВУ) – это не алгоритм, а только запись алгоритма. Соответственно, компилятору принципиально доступны лишь структуры, нашедшие отражение непосредственно в записи, но не сам алгоритм. Один и тот же алгоритм вообще можно записать многими способами и на разных языках. Так что компилятор, в процессе перевода с входного ЯВУ на машинный язык, оптимизирует языковые конструкции. Компилятор не видит алгоритм и не может его оптимизировать. Разработчик, в теории, способен оптимизировать именно алгоритм, это следует из того, что разработчик как раз “переводит” (записывает) алгоритм на ЯВУ (но, конечно, лишь в том случае, если код пишется не силами очередного ИИ/LLM/ChatGPT, выстраивающего “токены” в псевдомарковскую цепь). Поэтому иногда нужен ассемблер.
Есть хрестоматийный “обратный” пример, иллюстрирующий ситуацию обработки структур, которые образует запись алгоритма – “схлопывание” циклов: оптимизирующий компилятор обнаруживает, что промежуточный результат шагов циклического выполнения команд, записанного в программе, не используется, поэтому просто выкидывает цикл, схлопнув структуру, вся внутренняя сложность которой оказалась сводимой к прямому подключению ввода к выводу. Тексты программ не несут смысла сами по себе, а в этом случае за записью программы, как выясняется, стояли разные “алгоритмы”. Разработчик хотел измерить производительность некоторой реализации функции, вызывая её много раз в цикле; а компилятор стремился уменьшить время выполнения программы – количество шагов, приводящее к достижению результата: как говорится, если результат тот же, то зачем тратить больше вызовов?
Компилятор не может видеть алгоритм, но при этом ещё и должен генерировать более или менее универсальный код, пригодный и для исполнения на различных версиях совместимой аппаратуры, и для совсем разных платформ. То есть, уже из-за разнообразия платформ, компилятору затруднительно повсеместно использовать конкретные аппаратные оптимизации даже для конкретных алгоритмических элементов. Ассемблер, в руках разработчика, позволяет это сделать. Тем не менее, так как модели вычислений разных платформ очень близки, то и высокоуровневые решения дают хороший, эффективный результат.
С другой стороны, использование ассемблера вовсе не исключает эффект от “фокусов оптимизации” современных “больших” процессоров (amd64 и пр.): видимые снаружи такты, записанные за выполнением конкретной операции, не обязательно соответствуют реальным тактам – тут накладывается не только параллельное исполнение (его ещё и может быть несколько уровней), но и возможное “предварительное” выполнение, предсказание ветвлений и так далее. Однако ассемблер всё же ближе к аппаратуре, поэтому в целом ряде случаев позволяет сильно повысить именно алгоритмическую точность описания, а не языковое удобство, как в ЯВУ. Типичный пример – использование длинных регистров. Но многое зависит от конкретной ситуации – современный компилятор очень часто генерирует код не хуже, чем написал бы на ассемблере опытный разработчик. Особенно, если учитывать необходимый контроль, которым принято обставлять сложный код для повышения его надёжности: контроль обращений к памяти, адресные таблицы и так далее.
Комментировать »
Нередко можно услышать или прочитать, что вероятность совпадения биометрических показателей у разных людей “исчезающе мала”, а поэтому совпадений не может быть на практике. Вообще, при оценке подобных статистических показателей обязательно нужно учитывать то, как показатели измеряются, преобразуются и что именно сравнивается, что именно считается за “совпадение”, а что – за “различие”.
Например, венозный рисунок ладони, считываемый некоторой аппаратурой, – он, может, разный у каждого человека, но сравнение-то будет выполняться после обработки “картинки” этого рисунка по некоторому алгоритму. Алгоритм, предположим, “сжимает” геометрический рисунок до 64 битов идентификатора, используя именно важные элементы (пересечения, фрагменты сетки, углы и пр., это тут не так важно). Получается что-то вроде хеш-функции или “функции сжатия”. В идеальной ситуации даже одно минимальное отличие рисунков должно давать другой код. При этом, конечно, возникает идея сделать не просто хеш-функцию, а такую хеш-функцию, которая ещё и обладает нужной локализацией, то есть, “близкие” рисунки дадут “близкие” значения. Кстати, такие функции сжатия или хеш-функции называются Locality-Sensitive Hash (LSH). Они удобны далеко не только в обработке биометрии. Однако есть побочные эффекты. С одной стороны, подходящая локализация поможет добавить ещё один слой устойчивости к ошибкам считывания, но, с другой стороны, может выдавать ложное положительное срабатывание.
В любом случае, сжатие какой-то исходной биометрии в некоторые коэффициенты может приводить к нежелательным эффектам: например, функция преобразования будет терять какие-то важные отличия. Если используется массив коэффициентов, то ошибка может распространяться по каким-то из них, по самым “слабым”, так как на следующих этапах сранивать будут уже подмножества. Всё это относится не только к упомянутым венозным рисункам, но и к биометрии в целом. В данной области любое преобразование должно быть устроено надёжным и, главное, однозначным способом, сохраняющим избирательность на нужном уровне, гарантированно превышающем вариативность в реальной биологической выборке, представителей которой предлагается различать. Потому что если биометрический показатель хорошо отображается в 64 бита, то это, вроде, достаточно много. Однако, если реально возможно попадание только, предположим, в 16 бит, – пусть и по максимально “далёким”, в смысле привычной двоичной системы, значениям, – то это уже несравнимо хуже: в случае массовой системы, из-за парадокса дней рождения, проблемы с совпадением измерений проявятся очень быстро.
Насколько вообще должны отличаться результаты считывания венозного рисунка, чтобы признать, что это были показатели разных людей? Обратите внимание: для самого идеального рисунка – более или менее понятно, что даже “минимальные” отличия будут означать, что это другой человек. Но сравниваются-то изображения. И ввести тут корректное, для решаемой задачи, понятие “минимальности” отличий очень и очень сложно.
Поэтому-то применение непонятных и непрозрачных алгоритмов “нейросетей” в подобной автоматизированной биометрии не к месту. Процесс взвешивания коэффициентов в процессе “обучения” может оптимизировать фильтры относительно совсем не тех показателей, которые обеспечивают различимость на настоящей выборке. Тем более, что в нейросетевые системы можно вносить бекдоры. Эти бекдоры используются как раз для того, чтобы совершенно непохожий, но специально подготовленный, биометрический объект “свернулся”, после преобразования, в какой-то другой, являющийся универсальным.
Использование биометрии в разных типах систем контроля тоже сильно различается. Одно дело, если это обособленная система доступа в помещения (классическая СКУД). В такой системе, оператор, когда создаёт учётную запись нового сотрудника с допуском, может обнаружить, что считывание, предположим ладони, приводит к коду, который уже есть в базе данных. Так что случайное (или не случайное) совпадение тут же будет выявлено. (Биометрия вообще должна бы использоваться только при участии оператора-человека, но сейчас от этого элемента постоянно отступают.) Другое дело, когда биометрический показатель, поступивший из внешней системы, используется для поиска по “неопределённой выборке”. Тут проблемы возникают вовсе не в области, где, якобы, “вероятность совпадения биометрии почти нулевая”, а в области качества сжатия параметров перед реальным сравнением – и вероятность совпадения значений функции сжатия (хеш-функции) уже может быть совсем не нулевой. Тем более, когда это не криптографическая хеш-функция, а не ясно как подкрученная “нейросеть” с анализом изображений.
Комментировать »
В LibreSSL версии 3.9.0 полностью удалена поддержка криптосистем ГОСТ (шифр, подпись и хеш-функция) – код убрали из состава компилируемых модулей. В соответствующем комментарии сказано, что причина в низком качестве имеющегося кода, который, к тому же, мешает коду в других модулях, и что разработчики не против поддержки ГОСТ-криптосистем пакетом LibreSSL, но этот код должен быть качественным и у него должен быть мейнтейнер.
Комментировать »
Отдельные занимательные эффекты, связанные с переключением морфологических веток, можно наблюдать в автоматических переводчиках с ИИ. Кстати, надо сказать, что автоматический переводчик “Яндекса“, приправленный LLM ИИ, при переводе специальных фраз с английского на русский действует несколько лучше переводчика от Google (не менее приправленного). Вот примеры, иллюстрирующие и переключение интерпретаций по контексту, и качество.
1.
Исходная фраза:
“As a sailor once said: having logs removed in timely manner keeps bank totally speckless.”
Google:
Как однажды сказал один моряк: если вовремя убрать бревна, берег будет совершенно чистым.
“Яндекс”:
Как однажды сказал один моряк: своевременное удаление бревен позволяет сохранить берег совершенно чистым.
2.
“As a bookkeeper once said: having logs removed in timely manner keeps bank totally speckless.”
Google:
Как однажды сказал бухгалтер: своевременное удаление бревен делает банк совершенно чистым.
(Здесь Google предпочёл “брёвна” в банке, а не несколько более уместные “журналы”, как “Яндекс”.)
“Яндекс”:
Как однажды сказал один бухгалтер: своевременное удаление журналов позволяет сохранить банк полностью незапятнанным.
3.
“Bookkeeper mumbled the old nautical adage: having logs removed in timely manner keeps bank totally speckless.”
Google:
Бухгалтер пробормотал старую морскую поговорку: своевременное удаление бревен делает берег совершенно чистым.
“Яндекс”:
Бухгалтер пробормотал старую морскую пословицу: “своевременное удаление бревен сохраняет банк совершенно чистым”.
(Использование nautical успешно превращает logs в “брёвна”, сохранив “банк” силами слова bookkeeper, в котором три “дуплета”, но зато переводчик “Яндекса” даже кавычки поставил.)
Комментировать »
У рассылки SMS с устройств пользователей, которую, как пишут, предлагает Telegram, есть ценный “идейный” аспект: распределённую сеть, составленную из абонентских устройств, можно использовать куда как интереснее, чем просто в роли инструмента бесплатных SMS-рассылок. Смартфон, с работающим приложением, может обнаруживать другие устройства: WiFi, Bluetooth разных видов, акустика (это особенный метод, не только совместимый с “умными” колонками, но и вообще – кроссплатформенный и эффективно работающий в обе стороны).
Поэтому, в обмен на “премиум-доступ”, можно построить активную сенсорную сеть, с привязкой к точному времени и координатам, которая будет видеть перемещение не только различных пользователей приложения-мессенджера, но и прочих носителей смартфонов, равно как и выявлять устройства типа ноутбуков, беспроводных наушников, браслетов, часов с “картами и GPS”, “умных” (не менее, чем колонки) телевизоров, специальных “маячков”, а также и других подобных – тут есть где развернуться.
Комментарии (5) »
Изолированные, закрытые вычислительные среды принципиально не удаётся “поставить на системный мониторинг” привычными средствами. Обычный подход, когда на каждом сервере (виртуальной машине или физической) установлено несколько программ-агентов (ср., конечно, Zabbix и др.), которые через сетевой доступ управляются центральным “сервером-мониторинга” – это, как говорится, “радость пентестера”: и действительно, агенты позволяют выполнять код на целевых системах и делать это по командам с центрального узла. Принято думать, что “исполнение кода” не свойственно агентам, а имеющийся инструментарий по запуску локальных команд, если про него вспомнили при настройке, можно отключить. Это, однако, сильно упрощённое понимание.
Программа-агент – это именно программа, исполняемая на удалённой системе, и если в эту программу могут поступать по некоторому, заведомо доверенному, каналу данные от центрального сервера, это означает, что данный канал может быть использован для компрометации программы-агента и исполнения произвольного кода через ту или иную уязвимость. То есть, даже в том случае, когда штатное “выполнение команд” отключено. Понятно, что схема с уязвимостью агентов существенно сложнее, чем захват сервера управления (мониторинга), при этом использование уязвимости агента, скорее всего, требует наличия доступа к серверу управления: так что нужно и то, и другое. Но зато в качестве большого бонуса приходит доступ сразу к большому количеству систем, через единую точку, которая, ещё раз, является доверенной.
Отчасти проблема решается настройкой агентов в пассивный режим: агент мониторинга больше не обращается на центральный сервер за командами и инструкциями, но присылает отчёты о состоянии локальной вычислительной среды в одностороннем порядке, с заданной периодичностью. Это вполне себе типовая настройка, но используют её не так часто.
Естественно, можно настроить различные фильтры, которые будут в сторону защищаемой системы (и в обратную сторону) пропускать только пакеты с конкретной структурой, можно даже переписывать эти пакеты на стороне фильтра. Уязвимым окажется фильтр, но он может быть выполнен очень простым, на простой аппаратуре – некоторые даже используют что-нибудь типа Arduino. Собственные решения для мониторинга на этом направлении вообще лучше: можно и режим сделать полностью односторонним, пассивным, и “развязки” разной степени “гальваничности” устроить.
Основной смысл типичного системного мониторинга в том, чтобы предотвратить проблему, заранее обнаружив угрожающее состояние. В теории. Это не всегда так на практике, поскольку есть ещё резервирование инфраструктуры и другие важные направления. Наличие развитого мониторинга с кучей отслеживаемых параметров может создавать ложное чувство предсказуемости и контроля над ситуацией. При этом отказы всё равно происходят внезапно, но иногда – в результате излишнего доверия мониторингу. Что-то отключают, что-то включают – жонглирование параметрами распространено едва ли не больше, чем исправление возникающих проблем. Наблюдаемое “мерцание” сигналов может приучить не обращать излишнего внимания на изменения (чтобы не слишком-то доверять мониторингу, см. предыдущее предложение). Особенно, когда отказы всё равно происходят внезапно. Отсюда и крайние меры: невозможность дополнительного мониторинга изолированной системы вынуждает использовать в качестве события “мониторинга” сам отказ. Иногда, такой подход – это неустранимая архитектурная особенность, проявляющаяся неявно.
Комментировать »
Новый