Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2025-68621 | Kitploit
Инструменты/GitHubGitHub/sivaadityacoder/cve-2025-68621
Анализ уязвимостейЭксплуатацияВеб-безопасностьКриптографияСтатьи и ИсследованияОбучение и Образование
GitHubsivaadityacoder/cve-2025-68621

CVE-2025-68621

Репозиторий
3 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2025-68621 — Тайминг-атака на Trilium Notes через /api/login/sync

Серьёзность: ВЫСОКАЯ (CVSS 7.4) Затронутое ПО: TriliumNext/Trilium < 0.101.0 Тип уязвимости: CWE-208 – Наблюдаемое расхождение во времени (Observable Timing Discrepancy) Исправлено в: Trilium 0.101.0 (PR #8129) Опубликовано: 2026-02-06 | Зарезервировано: 2025-12-19


Содержание

  1. Мой подход
  2. Корневая причина
  3. Воздействие
  4. Исправление
  5. Основные выводы
  6. Хронология
  7. Ссылки

Мой подход

Что такое Trilium Notes?

Trilium Notes — это приложение с открытым исходным кодом для ведения иерархических заметок, работающее на разных платформах и предназначенное для построения больших личных баз знаний. Оно поддерживает:

  • Самостоятельно размещаемый (self-hosted) сервер, с которым могут синхронизироваться несколько клиентов
  • Богатые типы заметок (текст, код, канвас, диаграммы)
  • Мощный API для написания скриптов

Функция синхронизации позволяет клиенту Trilium проходить аутентификацию на сервере Trilium, чтобы заметки оставались синхронизированными между устройствами. Эта конечная точка синхронизации — точка входа для CVE-2025-68621.

Что такое тайминг-атака?

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

Классический пример — сравнение строк:

root@kitploit:~
"correct_password" !== "aorrect_password"   → fails at position 0 → fast
"correct_password" !== "cXrrect_password"   → fails at position 1 → slightly slower
"correct_password" !== "correct_password"   → matches fully     → slowest

Большинство языков программирования сравнивают строки посимвольно и останавливаются, как только найдено несовпадение (ранний выход). Это означает:

  • Догадка, совпадающая по первому байту, занимает чуть больше времени, чем та, что не совпадает сразу.
  • Отправляя тысячи догадок и усредняя время ответа, злоумышленник может статистически определить, какой байт верен, — позиция за позицией, — пока не будет восстановлен весь секрет.

Исправление заключается в использовании функции сравнения за постоянное время (constant-time comparison), которая всегда проверяет каждый байт, независимо от того, где произошло несовпадение.

Как была обнаружена уязвимость

Уязвимость была обнаружена в ходе ручного анализа кода логики аутентификации Trilium. Исследователь изучил процесс входа через синхронизацию в apps/server/src/routes/api/login.ts и заметил следующий фрагмент в функции loginSync() (примерно строка 111):

root@kitploit:~
const documentSecret = options.getOption("documentSecret");
const expectedHash   = utils.hmac(documentSecret, timestampStr);
const givenHash      = req.body.hash;

if (expectedHash !== givenHash) {          // ← VULNERABLE LINE
    return [400, { message: "Sync login credentials are incorrect..." }];
}

Красный флаг — использование встроенного оператора JavaScript !== для сравнения HMAC-хешей. Оператор !== не выполняется за постоянное время — он завершается, как только находит отличающийся символ. Поскольку сравнение выполняется над обычными строками (без использования криптографически безопасной функции сравнения), время ответа раскрывает информацию о том, сколько начальных байтов догадки злоумышленника верны.

Затем исследователь задался вопросом:

«Можно ли усилить эту небольшую разницу во времени настолько, чтобы по сети восстановить полный 44-символьный HMAC-хеш в кодировке Base64?»

Ответ оказался да — при достаточном количестве повторных измерений и некотором статистическом анализе сигнал поднимается над шумом.

Алгоритм атаки

Когда клиент Trilium хочет выполнить синхронизацию, он вызывает POST /api/login/sync с телом JSON вида:

root@kitploit:~
{
  "timestamp":   "2025-12-19T10:00:00.000Z",
  "syncVersion": 34,
  "hash":        "<HMAC-SHA256 of documentSecret + timestamp, Base64-encoded>"
}

Восстановление байт за байтом работает следующим образом:

root@kitploit:~
For position = 0 to 43:
    For each candidate character c in charset (A-Z, a-z, 0-9, +, /, =):
        Send SAMPLES requests with hash = known_prefix + c + padding
        Record average response time
    Best character = candidate with highest average time
    Append best character to known_prefix

После 44 итераций (по одной на каждый символ Base64) восстанавливается полный 44-символьный HMAC-хеш.

Практические требования:

  • >100 000 HTTP-запросов в сумме (50 выборок × 65 символов алфавита × 44 позиции ≈ 143 000)
  • >1 000 различных исходных IP-адресов из-за ограничения частоты запросов в Trilium (требуются ротация прокси или ботнет)
  • Низкий сетевой джиттер между атакующим и сервером (лучше всего подходит LAN или стабильное облачное соединение)
  • Таймер с высокой точностью (time.perf_counter() в Python обеспечивает разрешение в наносекундах)

Доказательство концепции (PoC)

См. poc.py — полностью аннотированный Python-PoC.

Краткое описание того, что делает PoC:

  1. Перебирает все 44 позиции символов Base64 в HMAC-хеше.
  2. Для каждой позиции перебирает все символы из набора Base64 (A–Z, a–z, 0–9, +, /, =).
  3. Отправляет 50 HTTP POST-запросов к /api/login/sync для каждого кандидата и измеряет медианное время ответа.
  4. Выбирает кандидата с наибольшим медианным временем ответа как правильный символ.
  5. После восстановления всех 44 символов проходит аутентификацию с восстановленным хешем.

Отказ от ответственности: Этот PoC предоставлен исключительно в образовательных целях и для ответственных исследований в области безопасности. Не используйте его против систем, которыми вы не владеете или на тестирование которых у вас нет явного письменного разрешения.


Корневая причина

Операторы JavaScript !== (и ===) выполняют лексикографическое сравнение с ранним выходом. Уязвимая строка в apps/server/src/routes/api/login.ts:

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

Поведение с ранним выходом создаёт измеримую разницу во времени для каждого совпадающего байта:

Каждый дополнительный совпадающий байт требует крошечного дополнительного количества процессорного времени δ. На тысячах выборок среднее время ответа для догадки «верный байт N» измеримо больше, чем для догадки «неверный байт N», что раскрывает достаточно информации для восстановления полного HMAC-хеша посимвольно.

Разбор оценки CVSS

Строка вектора: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N


Воздействие

Успешная эксплуатация даёт злоумышленнику:

  • Полный доступ на чтение ко всем заметкам, включая метаданные зашифрованных заметок
  • Полный доступ на запись — злоумышленник может создавать, изменять или удалять заметки
  • Постоянный доступ — восстановленный хеш можно использовать повторно (в пределах окна действия отметки времени)

Это особенно серьёзно для пользователей, которые хранят чувствительные личные данные (пароли, личные документы, дневниковые записи) в своей базе знаний Trilium.


Исправление

Исправление заменяет сравнение через !==, не выполняющееся за постоянное время, встроенной функцией Node.js crypto.timingSafeEqual():

До (уязвимо):

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

После (безопасно):

root@kitploit:~
import * as crypto from "crypto";

const expectedBuffer = Buffer.from(expectedHash);
const givenBuffer    = Buffer.from(givenHash ?? "");

if (expectedBuffer.length !== givenBuffer.length ||
    !crypto.timingSafeEqual(expectedBuffer, givenBuffer)) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

crypto.timingSafeEqual() всегда сравнивает каждый байт, поэтому время выполнения не зависит от того, сколько байтов совпало. Тайминг-сигнал исчезает.

См. vulnerable.ts и fix.ts — примеры кода рядом для сравнения.

Как обновиться

Если вы запускаете собственный (self-hosted) сервер Trilium, немедленно обновитесь до версии 0.101.0 или новее.

root@kitploit:~
# Docker example
docker pull zadam/trilium:0.101.0

Основные выводы

  1. Никогда не используйте === / !== для сравнения секретов. Операторы равенства в JavaScript не выполняются за постоянное время. Любое сравнение HMAC-хешей, токенов или паролей с помощью === / !== — это потенциальный тайминг-оракул.

  2. Всегда используйте crypto.timingSafeEqual() в Node.js (или эквивалент в вашем языке/рантайме) при сравнении криптографических значений. Это стандартный API, созданный специально для этой задачи.

  3. Тайминг-атаки реально работают через сеть. Хотя наносекундные различия кажутся невозможными для обнаружения через интернет, статистические методы и достаточное количество выборок позволяют извлечь чёткий сигнал из зашумлённых измерений — особенно в средах с низким джиттером.

  4. Одного ограничения частоты запросов недостаточно. Даже с ограничением частоты на IP злоумышленник, имеющий доступ к ротации прокси или ботнету, всё равно может накопить достаточно выборок для эксплуатации тайминг-разницы.

  5. Проверка HMAC заслуживает такого же внимания, как сравнение паролей. HMAC-хеши — это секреты. Относитесь к любому сравнению секретного значения так, как будто тайминг-побочные каналы могут быть использованы.

  6. Анализ кода на предмет криптографических паттернов обязателен. Эта уязвимость была найдена при ручном анализе — одна строка кода, которая выглядела безобидно, но имела серьёзные последствия для безопасности. Специализированные криптографические аудиты и аудиты безопасности помогают выявлять такие проблемы на ранних стадиях.


Хронология

ДатаСобытие

Ссылки


Этот репозиторий поддерживается в образовательных и исследовательских целях в соответствии с принципами ответственного раскрытия информации.

Скачать инструмент
Догадка против ожидаемогоСравнено байтВремя
Неверный байт 01~T
Верный байт 0, неверный байт 12~T + δ
Верные байты 0–1, неверный байт 23~T + 2δ
………
Все 44 байта верны44~T + 43δ
МетрикаЗначениеПричина
Базовый балл7.4 ВЫСОКИЙ
Вектор атакиСетевой (N)Эксплуатируется через интернет
Сложность атакиВысокая (H)Требует множества запросов и стабильного тайминга
Требуемые привилегииОтсутствуют (N)Учётная запись не нужна
Взаимодействие с пользователемОтсутствует (N)Жертве не нужно ничего делать
Область воздействияБез изменений (U)Затронут только сервер Trilium
КонфиденциальностьВысокая (H)Вся база заметок доступна для чтения
ЦелостностьВысокая (H)Злоумышленник может записывать/изменять заметки
ДоступностьОтсутствует (N)Компонента отказа в обслуживании нет
2025-12-19CVE-2025-68621 зарезервирован GitHub Security
2025-12-21Открыт исправляющий PR #8129
2025-12-25PR объединён; выпущена Trilium 0.101.0
2026-02-06CVE опубликован публично
2026-02-09Добавлено обогащение от CISA ADP
РесурсСсылка
Рекомендация GitHub SecurityGHSA-hxf6-58cx-qq3x
Исправляющий pull requestTriliumNext/Trilium#8129
Запись CVE (CVEProject)CVE-2025-68621.json
CWE-208Наблюдаемое расхождение во времени (Observable Timing Discrepancy)
Репозиторий Trilium NotesTriliumNext/Trilium