FlawOpen

flawopen.com/Teardowns/cve-2026-61500-rejetto-hfs-predictable-session-key

● CVE-2026-61500 · CVSS 9.3[1] · Критический
Исследования · FlawOpen

CVE-2026-61500: предсказуемый ключ подписи сессий в Rejetto HFS

Rejetto HFS 3.0.0–3.2.0 использовала значения Math.random() для подписи сессий и при входе. По данным Horizon3, утечка позволяла подделывать сессии; VulnCheck сообщает о наблюдении эксплуатации с 1 октября. Обновитесь до 3.2.1 или новее; компрометация конкретной жертвы не подтверждена.[1], [4], [5]

💡 Простыми словами (ELI5)

Подпись cookie похожа на восковую печать на пропуске администратора. HFS создавала секрет печати из предсказуемой последовательности чисел, а вход раскрывал другие числа из той же последовательности. Зная секрет, можно подделать печать. Исправление использует криптографическую случайность Node.js.[1], [3]

Ключевые понятия и термины

Ключ подписи сессии
Секрет, которым Koa подписывает cookie сессии, чтобы обнаруживать подмену.[1], [3]
Math.random()
Общая псевдослучайная API, не предназначенная для создания криптографических секретов.[6], [4]
CWE-338
Использование криптографически слабого генератора псевдослучайных чисел; именно эта слабость указана в записи CVE.[1], [6]
Состояние PRNG
Внутреннее состояние, определяющее следующие псевдослучайные значения. Если один генератор используется для секрета и наблюдаемых значений, между ними могут обнаружиться связи.[4]
Контекст обнаружения
По данным Horizon3, исследовательская мультиагентная система с участием Mythos выявила и подтвердила эту цепочку уязвимостей HFS. Это описание исследовательской работы, а не уязвимость в Mythos и не доказательство автономной атаки ИИ на реальную установку HFS.[4]

Связи со стандартами

  • Ссылка CWE для слабого места, описанного в этом руководстве: CWE-338

Анализ первопричины

В записи CVE указаны HFS 3.0.0–3.2.0 и CWE-338. В upstream-коммите 59472e5 уязвимый код передавал Koa [randomId(30)]; randomId() использовал Math.random(). Исправление заменило это на [randomBytes(32).toString('base64url')] из node:crypto. В том же коммите публичный идентификатор рукопожатия при входе заменён с Math.random() на randomUUID(). Horizon3 сообщает, что доступные без аутентификации ответы входа раскрывали достаточно связанных выходов для восстановления состояния PRNG V8 и вычисления ключа подписи cookie. Поддельная сессия администратора открывала встроенные функции администрирования HFS, способные привести к выполнению кода на сервере. Здесь цепочка описана на высоком уровне без решателя, запросов и полезных нагрузок. По данным VulnCheck, Canary Intelligence начала наблюдать эксплуатационную активность 1 октября 2026 года; об этом сообщалось в отчёте от 2 октября. Телеметрия не указывает на конкретную скомпрометированную установку HFS.[1], [3], [4], [5]

Пошаговый сценарий атаки

Шаг 1

Доступна уязвимая версия HFS

Затронуты версии HFS 3.0.0–3.2.0. Метрики CVSS указывают на сетевой доступ без предварительных привилегий.[1], [2]

Шаг 2

Одна слабая последовательность выполняет две роли

HFS получала ключ подписи из Math.random(), а вход раскрывал связанные значения. Криптографический секрет нельзя получать из предсказуемого или наблюдаемого общего PRNG.[1], [3]

Шаг 3

Слабость преодолевает границу сессии

По данным Horizon3, выходные значения позволяли восстановить состояние PRNG и подделать подпись сессии для получения доступа администратора. Подробный метод восстановления не приводится.[4]

Шаг 4

Доступ администратора может привести к запуску кода

Horizon3 описывает цепочку до функции HFS server_code. По данным VulnCheck, Canary Intelligence начала наблюдать эксплуатационную активность 1 октября 2026 года, о чём сообщалось 2 октября; эта телеметрия не доказывает компрометацию конкретной установки.[4], [5]

Исходный код: Уязвимый vs Защищённый вариант

Фрагменты соответствуют реальному upstream-коммиту. randomBytes(32) даёт ключу 256 бит из криптографического модуля Node.js, а randomUUID() заменяет источник публичного идентификатора входа. Секреты для аутентификации сессий должны поступать из криптографического источника и не зависеть от наблюдаемых выходов прикладного PRNG. Обновитесь до HFS 3.2.1 или более новой поддерживаемой версии; это пояснение, а не отдельный патч. Это защищает только сгенерированное резервное значение: если задан COOKIE_SIGN_KEYS, каждый переданный ключ также нужно независимо создать криптографически стойким генератором, хранить в секрете и заменить при раскрытии.[3], [1]

Фрагмент исходного кода: src/index.ts (ключ подписи cookie) и src/api.auth.ts (идентификатор рукопожатия входа, коммит upstream 59472e5)

УЯЗВИМАЯ РЕАЛИЗАЦИЯ
import { httpStream, randomId } from './misc'

const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
  || [randomId(30)]
export const app = new Koa({ keys })

const sid = Math.random()
БЕЗОПАСНЫЙ ИСПРАВЛЕННЫЙ ВАРИАНТ
import { randomBytes, randomUUID } from 'node:crypto'

const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
  || [randomBytes(32).toString('base64url')]
export const app = new Koa({ keys })

const sid = randomUUID()

Чек-лист по защите системы для инженеров

Источники