limitations
Модель безопасности Meshtastic находится на пересечении нескольких противоречивых требований. Этот документ объясняет требования, компромиссы, которые они представляют, и характеризует текущие ограничения, выбранные для того, чтобы сделать Meshtastic удобным в использовании. Он также охватывает недавние изменения и предстоящие исправления.
Эта информация не нова, но до сих пор была разбросана по обсуждениям в Discord, проблемам в GitHub и комментариям в кодовой базе Meshtastic. Этот документ — попытка четко изложить всё в одном месте.
История
Сначала Meshtastic изначально был разработан для работы только с закрытыми, доверенными группами. Каналы Meshtastic шифруются с помощью предварительно разделённого ключа (PSK) и AES-CTR. Этот тип шифрования не включает аутентификацию, и поэтому любой, у кого есть PSK, может отправить сообщение от имени любого другого пользователя в этом канале.
AES-CTR имеет ещё одну уязвимость: он генерирует поток шифротекста для заданного вектора инициализации (IV), а фактический шаг шифрования выполняется путём XOR простого текста с этим потоком. В сообщениях канала Meshtastic этот IV представляет собой комбинацию Nodenum отправителя и PacketID данного сообщения. Это означает, что если злоумышленник сможет вывести точный открытый текст зашифрованного сообщения, он сможет повторно использовать комбинацию Nodenum и PacketID для отправки поддельных сообщений, даже не зная PSK канала. Это имеет ограниченную полезность из-за требования повторного использования PacketID и исходного NodeNum для получения совпадающего IV.
В своей первой итерации Meshtastic обрабатывал прямые сообщения (DM) путём простого использования существующего PSK канала и пометки DM как направленных только целевому узлу. Этот подход был приемлемым, когда Meshtastic использовался только малыми группами, но появление публичных сеток с потенциальными злоумышленниками значительно изменило ситуацию. Около года Meshtastic намеренно добавляет функции для защиты от этого сценария, но с минимальными нарушениями совместимости.
PSK DM в особенности были признаны проблемой, и новая система DM была внедрена в Meshtastic 2.5. Эта система использует криптографию с открытым ключом x25519 и AES-CCM для шифрования и аутентификации DM, отправляемых между узлами. Эти открытые ключи передаются внутри пакетов User, зашифрованных с использованием существующих PSK каналов.
Ограничения
Эта система по необходимости использует модель «доверие при первом использовании» (TOFU). Нет центрального органа для подписи ключей пользователей, и поэтому узлы сохраняют и удерживают первый объявленный открытый ключ для заданного номера узла. Это по сути жёсткое требование децентрализованной mesh-сети.
Эта проблема усугубляется ограниченной памятью для хранения узлов на узле Meshtastic. NodeDB ограничена 100 узлами на большинстве оборудования, и когда на сети появляется больше узлов, самый старый и наименее интересный узел вытесняется из NodeDB, чтобы освободить место для новых узлов. Исключение составляет избранные узлы, которые гарантированно не удаляются из NodeDB.
Комбинация модели TOFU и ограниченного оборудования приводит к проблеме. Когда узел вытесняется из NodeDB, прошивка Meshtastic не имеет способа подтвердить, что будущий пакет User не является подделкой этого номера узла с другим открытым ключом. Эта проблема усугубляется возможностью злоумышленника в канале быстро создать фальшивые узлы и заставить легитимные узлы вытесниться из NodeDB раньше.
Эта атака была предвидена при проектировании системы DM и принята как неизбежный результат создания ad-hoc децентрализованной mesh-сети. Снова нет центрального органа для подписи ключей. В результате в систему были встроены несколько мер защиты, чтобы минимизировать реальную полезность этой атаки.
Предназначенное поведение
Во-первых, хотя NodeDB ограничена 100 узлами на встроенном оборудовании, подключённый мобильный клиент способен хранить информацию о гораздо большем количестве узлов и сигнализировать пользователю, когда один из этих узлов появляется с другим открытым ключом. Именно это происходит, когда узел на клиенте отображается с красной иконкой ключа. Прошивка увидела другой открытый ключ для этого узла, и мобильный клиент знает, что он изменился.
Вторая основная мера защиты заключается в том, что узлы, помеченные как избранные, никогда не удаляются из NodeDB. Клиенты теперь автоматически помечают узлы как избранные при отправке DM этому узлу, ещё больше обеспечивая, что узел, с которым общался пользователь, остаётся тем же самым.
Прошивка meshtastic также поддерживает откат к старому поведению DM. Это строго контролируется с помощью булева значения «pki_encrypted» и поля байтов «public_key». Когда прошивка получает пакет из mesh, если этот пакет отправлен с использованием PKI-шифрования DM, bool устанавливается в true, а исходный открытый ключ копируется в поле байтов. DM, использующие старый метод PSK канала, по-прежнему будут приниматься и обрабатываться, но поле pki_encrypted устанавливается в false.
Пакеты, отправляемые с подключённого клиента, могут установить булево значение «pki_encrypted» в true и заполнить поле байтов public_key в пакете, отправляемом через локальный API. Если булево значение установлено в true, пакет будет отправлен только через PKI DM. Если байты заполнены, пакет будет отправлен только если открытый ключ в сообщении API совпадает с открытым ключом для этого узла в локальной NodeDB. Если булево значение не установлено в true, прошивка отправит пакет как PKI DM, если он действительно отправлен одному получателю и прошивка имеет открытый ключ для этого получателя. Исходящие сообщения откатятся к менее безопасному шифрованию канала, если открытый ключ для удалённого узла неизвестен и булево pki_encrypted не установлено.
Будущее ED25519
Несколько уязвимостей системы Meshtastic можно устранить путём добавления системы подписи сообщений к сообщениям канала. Поскольку у нас всё ещё ограничено пространство хранения NodeDB и пакеты LoRa ограничены максимальным размером 256 байт, практически обязательно, чтобы эта система подписи повторно использовала существующие пары открытого/закрытого ключа, а подписи были как можно меньше.
Повторно выдвигалось дополнительное предложение, что nodeNum должен выводиться из publicKey, чтобы минимизировать возможность злоумышленника подделать пакет User от существующего nodenum с новым открытым ключом. Хотя команда безопасности Meshtastic в целом согласна с разумностью этого предложения, его реализация как breaking change для mesh была нецелесообразной. Добавление подписанных сообщений на самом деле представляет возможность навязать этот новый источник nodenum, оставаясь обратно совместимым со старой системой.
Поддержка ED25519 всё ещё дорабатывается на момент написания этого документа, но текущий прототипный код использует систему XEdDSA из Signal, чтобы взять существующие подписи X25519 и повторно использовать их как подписи ED25519. Хотя это значительно улучшает гарантии безопасности системы Meshtastic, эти подписи имеют длину 64 байта, что существенно с учётом размера сообщений LoRa.
После того как узел успешно подпишет сообщение User с помощью этой схемы, бит HAS_XEDDSA_SIGNED устанавливается в битовом поле NodeInfoLite, что переводится в булево has_xeddsa_signed в сообщении NodeInfo.
После установки этого бита неподписанные пакеты user от этого источника будут отбрасываться. Пока что предстоит определить, как будут обрабатываться другие неподписанные пакеты. На данный момент рекомендация заключается в том, что короткие пакеты, которые могли бы быть подписаны, должны отбрасываться, если они неподписаны.