В продолжение предыдущей записки. Различные “аппаратурные” атаки, типа разновидностей 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 – это, что называется, технически строгий способ. Браузер, в таком случае, выведет сообщение о недоступности узла, а не предупреждение о несовпадении имён, которое пользователи привыкли преодолевать при помощи кнопки “Всё равно продолжить”.



Комментировать »

Объяснение, что “кубит находится одновременно в двух состояниях” – не слишком хорошее. Гораздо лучше говорить, что состояние кубита, взятое “в нулях и единицах”, не определено до момента измерения. Изменение распределения этой неопределённости при помощи преобразований конфигурации системы, с учётом будущих и потенциально возможных измерений, как раз и составляет теоретическую полезность квантовых вычислений. То есть, нет “нулей”, нет “единиц” – есть взаимодействующие неопределённости и теоретические алгоритмы, сужающие конфигурацию пространств вариантов, доступных на границах, по которым происходит взаимодействие (квантовое преобразование Фурье, предположим).



Комментарии (2) »

Воскресное чтение манускриптов. Известно, что в Древней Греции не только знали, что Земля круглая (это более или менее очевидно), но и сумели определить радиус Земли (что уже требует астрономических познаний). Вообще, предположение, будто древние были уверены, что Земля плоская, встречается сейчас гораздо реже неверного мнения о физических представлениях Аристотеля и падении тел, но встречается всё равно. Между тем, построение на основе наблюдений окружающей действительности “минимально непротиворечивой” модели, в которой Земля, тем не менее, плоская, заметно сложнее, чем вариант с шаром или сферой, который более или менее напрашивается, если некоторое время следить за движением небесных явлений и светил.

Ниже приведён скриншот манускрипта конца 13 века (Adv.MS.18.7.15, древнегреческий) из коллекции Национальной библиотеки Шотландии (в коей библиотеке электронные архивы, как и дистанционный доступ к ним, пока что сохраняются). Фрагмент, на минуточку, относится к переписанной грамматиком Планудом (скорее всего) работе философа Клеомеда, в которой пересказан метод определения периметра большого круга Земли (длины меридиана), использованный древним греком Эратосфеном. Плануд переписал труд Клеомеда в 13 веке (результат – на скриншоте), а исходный труд Клеомеда, как предполагается, относится к периоду с первого по четвёртый век н. э., а вот сам Эратосфен выполнял описанные геометрические расчёты на рубеже третьего и второго веков до н.э. То есть, тут, примерно, полторы тысячи лет, в ходе которых Земля описывается как круглая (круглая Земля, заметьте, тоже может перевозиться большой черепахой, но это другая история).

Cleomedes

Занятно, что на этой странице манускрипта дан чертёж, иллюстрирующий метод Эратосфена. Метод этот, как видно из чертежа и описания, состоял в измерении длины тени гномона и углов падения солнечных лучей в двух точках одного меридиана – в городах Сиене и Александрии, – в период летнего солнцестояния. Так как город Сиена находится на Северном тропике, то здесь в полдень, при летнем солнцестоянии, правильно установленный гномон не отбрасывает тени (потому что Солнце в зените), а в Александрии – тень у гномона есть. Предположив, что солнечные лучи параллельны, взяв расстояние между двумя городами и длину тени александрийского гномона, можно вычислить периметр окружности Земли с помощью планиметрии, как и продемонстрировано на чертеже (Земля на чертеже внизу).

Исходя из расстояния от Сиены до Александрии (по большому кругу) в 5000 стадиев, Эратосфен определил общую длину меридиана в 250 000 стадиев – соответствующая строка манускрипта выделена зелёными метками (середина скриншота): “ὁ ἄρα σύμπας κύκλος γίνεται μυριάδων εἴκοσι πέντε” – так будет в современной типографике, но в манускрипте записано с кучей скорописных сокращений (и прочих “смайликов”), поэтому на современные начертания букв не очень-то похоже. Само число, кстати, указано как двадцать пять мириад (μυριάδων, двадцать – εἴκοσι, пять – πέντε). Двадцать пять мириад стадиев, – то есть, примерно, от 44 до 52 тыс. км, – неплохо соответствует современным оценкам в сорок тысяч километров.



Комментировать »

“Коммерческий поставщик спутникового наблюдения” Umbra недавно сообщил, что там начали вводить в строй систему бистатической радиолокации с синтезированием апертуры на базе нескольких низкоорбитальных спутников. По ссылке есть пример снимка, этот же пример – рассматривается ниже. Вообще, речь про специализированный радар сантиметрового диапазона, а синтезирование апертуры и согласованная вычислительная обработка данных позволяют сильно улучшить показатели: разрешающую способность, обнаружение движущихся целей и пр. Сейчас спутников в этом проекте, как пишут, запущено всего восемь, два самых новых как раз и обеспечивают базу для бистатической радиолокации. Поддержку оказывает DARPA.

Понятно, что результат радара – это далеко не цветная картинка, полученная телескопом для публикации в Google Earth (см. наложение ниже). Но у радара целый ряд преимуществ, тем более, если речь идёт об орбитальной радиолокации с разнесением передатчика и приёмника. Такой орбитальный радар видит ночную часть земной поверхности, может просвечивать не только сквозь облака, но и через некоторые наземные укрытия; зондирующий радиосигнал с высокой разрешающей способностью позволяет отличать макеты техники от настоящей техники и, в теории, может даже извлекать сведения о подземных коммуникациях (находящихся на небольшой глубине в подходящих почвах) и обнаруживать подвижные субмарины в подводном положении (по спутному следу). Спутники Umbra находятся на высоте около 550 км (450 – 600 км), а низкая орбита тоже приносит свои преимущества, даже по сравнению с самолётами. (Но, например, на радарной картинке не видна надпись, нанесённая на основание плотины с иллюстрации ниже.)

В качестве иллюстрации работы бистатической радиолокации Umbra публикует изображение дамбы большой ГЭС в Пакистане.

Общий вид:
SAR image, UMBRA
(Cпутниковый радар Umbra.)

Выделен фрагмент, который ниже дан с увеличением до “пиксел в пиксел”:
SAR image, UMBRA
(Umbra.)

Фрагмент с большим разрешением
SAR image, UMBRA
(Umbra.)

Примерное наложение на снимок, доступный в Google Earth:
SAR image, UMBRA
Занятно, что совпадает почти вся техника, выставленная во дворе (Umbra/Google). От Umbra, кстати, есть немало данных в открытом доступе.



Комментировать »

Современные компиляторы хорошо умеют оптимизировать машинный код и обычно делают это гораздо лучше разработчика. Но нужно учитывать тот факт, что программа на некотором языке высокого уровня (ЯВУ) – это не алгоритм, а только запись алгоритма. Соответственно, компилятору принципиально доступны лишь структуры, нашедшие отражение непосредственно в записи, но не сам алгоритм. Один и тот же алгоритм вообще можно записать многими способами и на разных языках. Так что компилятор, в процессе перевода с входного ЯВУ на машинный язык, оптимизирует языковые конструкции. Компилятор не видит алгоритм и не может его оптимизировать. Разработчик, в теории, способен оптимизировать именно алгоритм, это следует из того, что разработчик как раз “переводит” (записывает) алгоритм на ЯВУ (но, конечно, лишь в том случае, если код пишется не силами очередного ИИ/LLM/ChatGPT, выстраивающего “токены” в псевдомарковскую цепь). Поэтому иногда нужен ассемблер.

Есть хрестоматийный “обратный” пример, иллюстрирующий ситуацию обработки структур, которые образует запись алгоритма – “схлопывание” циклов: оптимизирующий компилятор обнаруживает, что промежуточный результат шагов циклического выполнения команд, записанного в программе, не используется, поэтому просто выкидывает цикл, схлопнув структуру, вся внутренняя сложность которой оказалась сводимой к прямому подключению ввода к выводу. Тексты программ не несут смысла сами по себе, а в этом случае за записью программы, как выясняется, стояли разные “алгоритмы”. Разработчик хотел измерить производительность некоторой реализации функции, вызывая её много раз в цикле; а компилятор стремился уменьшить время выполнения программы – количество шагов, приводящее к достижению результата: как говорится, если результат тот же, то зачем тратить больше вызовов?

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

С другой стороны, использование ассемблера вовсе не исключает эффект от “фокусов оптимизации” современных “больших” процессоров (amd64 и пр.): видимые снаружи такты, записанные за выполнением конкретной операции, не обязательно соответствуют реальным тактам – тут накладывается не только параллельное исполнение (его ещё и может быть несколько уровней), но и возможное “предварительное” выполнение, предсказание ветвлений и так далее. Однако ассемблер всё же ближе к аппаратуре, поэтому в целом ряде случаев позволяет сильно повысить именно алгоритмическую точность описания, а не языковое удобство, как в ЯВУ. Типичный пример – использование длинных регистров. Но многое зависит от конкретной ситуации – современный компилятор очень часто генерирует код не хуже, чем написал бы на ассемблере опытный разработчик. Особенно, если учитывать необходимый контроль, которым принято обставлять сложный код для повышения его надёжности: контроль обращений к памяти, адресные таблицы и так далее.



Комментировать »

В свежих версиях браузера Chrome на сторону серверов Google предлагается передавать информацию о запрашиваемых URL в реальном времени – это такое “улучшение для безопасности”, развитие давно работающей технологии Safe Browsing, но с некоторыми занимательными особенностями.

Так, для сохранения “приватности”, во-первых, сведения передаются в виде части значения хеш-функции, полученной от URL (с некоторыми преобразованиями); во-вторых, передавать запросы планируется через прокси-серверы, которые будут удалять информацию об IP-адресах; в-третьих, сервер будет возвращать набор полных значений, совпавших по короткому префиксу запроса, а точное совпадение уже будет определять браузер локально. То есть, схема передачи данных напоминает onion-маршрутизацию: содержательная часть зашифровывается при помощи открытого ключа сервера, поэтому промежуточный узел-прокси полезных данных не видит; а сервер – не видит IP-адреса источника запроса, потому что его удалил прокси. В теории. Так как конкретному URL соответствует только часть значения хеш-функции, короткий префикс, то ответов, потенциально, может поступить много разных (это все значения, для которых совпал начальный префикс, предположим, 32 бита). Такой расклад дополнительно маскирует исходный URL из браузера. В описании есть даже картинка – см. ниже, – однако ничего не сказано о том, какой ключ используется для зашифрования данных ответа.

Google Safe Browsing and Proxy
(Image: Google.)

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

Но главное тут в том, что схему можно развивать: первый шаг – отправка информации об URL в реальном времени на “разрешающий” сервер, для определения статуса блокирования; на следующих шагах – можно передавать больше данных.



Комментировать »

В конце 2022 года я добавил в DNS для dxdt.ru HTTPS-запись, которая тогда была описана в черновике RFC. В ноябре 2023 года черновик стал RFC 9460, где определяется способ публикации в DNS дополнительной информации о параметрах подключения к сервисам, связанным с данным именем. Например, это могут быть параметры для TLS/HTTPS, в том числе, ключи (см. ECH). Особенность использования DNS тут в том, что параметры можно получить до подключения, это, в свою очередь, позволяет устанавливать скрытые подключения.



Комментировать »

Воскресное чтение манускриптов. В этот раз – небольшой скриншот манускрипта Barb.gr.580 (древнегреческий, видимо, 11 или 12 век) из Ватиканской Апостольской библиотеки. На скриншоте небольшой фрагмент одного из комментариев (тридцать второго, если точнее) Иоанна Златоуста к Евангелию от Матфея. Этот фрагмент, заканчивающийся узнаваемым сочетанием слов – “учителями и врачами”, – содержит сразу несколько занятных сокращений, которые распространены в манускриптах соответствующего типа и периода.

Vat.Barb.Gr.580

Например, можно видеть упоминавшийся недавно на dxdt.ru “греческий амперсанд“, начертание которого здесь практически совпадает с лигатурой ϗ из Unicode. Это сокращённая запись слова καί, на скриншоте – четвёртая снизу строка, справа, отмечено красной стрелкой. Сокращённая запись сотрудником скриптория использована в конце строки, а в других случаях, рядом, καί вполне себе записывается полностью.

Пара других примеров труднодоступной для чтения скорописи отмечены в конце первой строки скриншота: левее – скорописью записано φησὶν (“говорит”), а следующее загадочное сочетание лигатур – это ἐπει в ἐπειδή (“когда”, “после того как”).



Комментировать »

Reuters раскрывает в эксклюзивном материале очередной секрет Полишинеля: SpaceX, пишет Reuters, строит “сеть из сотен спутников-шпионов” в интересах профильного штатовского агентства (NRO). Спутниковая сеть позволит вести мониторинг всей земной поверхности.

Цитата из записки про SpaceX и орбитальный радар, опубликованной на dxdt.ru в 2018 году: “получаем адаптивный орбитальный радиолокационный комплекс, который наблюдает всю поверхность Земли – технология, сошедшая со страниц научно-фантастических романов”. История движется, и теперь можно написать, что технология “сошла со страниц эксклюзивных публикаций Reuters”.

Направление это весьма интересное, так что про особые возможности больших группировок низкоорбитальных спутников, – в основном, это SpaceX/Starlink, – я писал не раз:

Инфракрасные сенсоры на орбите;
Низкоорбитальные сенсоры как наблюдательные сети;
Наземные терминалы Starlink как элементы радара;
Спутниковые системы для ЭМ-атак;
Starlink и взаимодействие с наземными GSM-сетями.



Комментировать »