Уязвимость к атаке man-in-the-middle и способы защиты

Атака man-in-the-middle (MITM) возникает в момент, когда канал связи между двумя сторонами оказывается под контролем третьей стороны, способной читать, изменять или подменять передаваемые данные. В веб-приложениях, использующих криптографию на стороне клиента, включая решения на базе Stanford JavaScript Crypto Library (SJCL), такая угроза особенно критична из-за высокой зависимости от корректной передачи ключевого материала и исходного кода приложения.

В JavaScript-среде MITM может проявляться не только на уровне сетевого трафика, но и на уровне доставки самого кода (например, через подмену скриптов при отсутствии HTTPS или компрометацию CDN).


Модель угроз в веб-криптографии

Основные точки атаки MITM в приложениях с SJCL:

  • перехват начального обмена ключами
  • подмена публичных ключей
  • внедрение вредоносного JavaScript-кода
  • модификация сообщений до их шифрования или после расшифровки
  • атаки на сессию (session hijacking)

Особенность браузерной среды заключается в том, что криптографический код и данные выполняются в одном доверенном контексте. Если этот контекст скомпрометирован, криптография теряет смысл.


Роль SJCL в криптографической защите

Stanford JavaScript Crypto Library предоставляет набор примитивов для симметричного шифрования, HMAC, хэширования и работы с эллиптическими кривыми.

Ключевые модули:

  • sjcl.encrypt / sjcl.decrypt — симметричное шифрование
  • sjcl.ecc — эллиптическая криптография
  • sjcl.hash — хэш-функции
  • sjcl.misc.hmac — коды аутентификации сообщений
  • sjcl.random — генерация случайных чисел

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


Почему MITM опасна при использовании SJCL

Рассмотрим типичный сценарий обмена ключами без аутентификации:

  1. Клиент генерирует публичный ключ
  2. Сервер отправляет свой публичный ключ
  3. Стороны вычисляют общий секрет через ECDH

Если атакующий находится между ними, он может:

  • подменить публичный ключ сервера своим
  • установить два разных ключа: с клиентом и сервером
  • расшифровывать и повторно шифровать весь трафик

В SJCL это особенно опасно при использовании sjcl.ecc.elGamal или ECDH-обменов без проверки подлинности ключей.


Классический пример уязвимого обмена

// Упрощённый пример ECDH без аутентификации
const client = sjcl.ecc.elGamal.generateKeys(256);
const serverPublic = getServerPublicKey(); // может быть подменён

const sharedSecret = client.sec.dh(serverPublic);

Если serverPublic получен через незащищённый канал (HTTP, уязвимый WebSocket), MITM может заменить его на свой ключ.


Основные способы защиты от MITM

Использование TLS как обязательного уровня

На практике базовой защитой выступает HTTPS (TLS). SJCL не заменяет транспортный уровень.

Ключевой момент:

  • криптография в SJCL работает поверх TLS
  • TLS предотвращает подмену ключей и кода на уровне сети

Без TLS любые криптографические операции в браузере становятся уязвимыми к MITM.


Аутентификация ключей

Для защиты ECDH необходимо подтверждение подлинности ключей.

Используются подходы:

  • цифровые подписи публичных ключей
  • сертификаты (X.509)
  • предварительное доверие (TOFU — trust on first use)
  • проверка fingerprint (отпечатка ключа)

Пример проверки отпечатка:

const pubKey = serverPublic.serialize();
const hash = sjcl.hash.sha256.hash(pubKey);
const fingerprint = sjcl.codec.hex.fromBits(hash);

if (fingerprint !== trustedFingerprint) {
    throw new Error("Key mismatch - possible MITM");
}

Подпись ключей с использованием ECC

SJCL поддерживает подписи через ECDSA:

const keys = sjcl.ecc.ecdsa.generateKeys(256);

const signature = keys.sec.sign(sjcl.hash.sha256.hash(message));
const valid = keys.pub.verify(sjcl.hash.sha256.hash(message), signature);

В контексте защиты от MITM ключи серверов подписываются доверенным центром или заранее известным ключом.


HMAC как защита целостности сообщений

MITM часто не только перехватывает, но и модифицирует сообщения. Для защиты используется HMAC:

const key = sjcl.codec.utf8String.toBits("shared-secret");
const hmac = new sjcl.misc.hmac(key, sjcl.hash.sha256);
const tag = hmac.encrypt(message);

При изменении сообщения проверка HMAC провалится, что выявляет вмешательство.


Проблема подмены JavaScript-кода

Отдельный вектор MITM — подмена самой библиотеки SJCL или пользовательского кода.

Риски:

  • внедрение вредоносного скрипта вместо SJCL
  • изменение алгоритма шифрования
  • утечка ключей до шифрования

Основная защита:

  • загрузка только через HTTPS
  • Subresource Integrity (SRI)
  • контроль версий зависимостей

Пример SRI:

<script src="sjcl.js"
        integrity="sha384-..."
        crossorigin="anonymous"></script>

Ошибки архитектуры, усиливающие MITM-риски

На практике уязвимости возникают не из-за SJCL, а из-за неправильного использования:

  • передача ключей через HTTP
  • отсутствие проверки сертификатов
  • хранение ключей в localStorage без защиты
  • генерация ключей на стороне клиента без аутентификации сервера
  • использование ECDH без подписи ключей

Комбинированная модель защиты

Надёжная схема с использованием SJCL обычно включает:

  • TLS как базовый транспортный слой
  • ECDH для согласования ключа
  • ECDSA или RSA для аутентификации
  • HMAC для проверки целостности сообщений
  • проверку fingerprint ключей на клиенте

Такая комбинация устраняет ключевую проблему MITM: невозможность незаметной подмены ключевого обмена.


MITM в контексте браузерных атак

Даже при корректной криптографии возможны дополнительные сценарии:

  • компрометация расширений браузера
  • вредоносные прокси
  • корпоративные MITM-прокси с установленными root-сертификатами
  • XSS, приводящий к перехвату ключей до шифрования

SJCL не может защитить от атак, происходящих внутри доверенного исполнения JavaScript-контекста. В этом случае нарушается сама модель доверия.


Практическая модель безопасного обмена с SJCL

Типовой безопасный поток:

  1. соединение устанавливается через HTTPS
  2. сервер отправляет подписанный публичный ключ
  3. клиент проверяет подпись через заранее известный ключ
  4. выполняется ECDH-обмен
  5. сообщения защищаются через AES + HMAC
  6. каждая сессия имеет уникальный ephemeral key

Критический аспект: границы ответственности SJCL

Stanford JavaScript Crypto Library предоставляет криптографические примитивы, но не реализует защищённый протокол передачи ключей. Защита от MITM достигается только при построении полного протокола, включающего:

  • аутентификацию
  • безопасный транспорт
  • проверку целостности
  • управление ключами

Без этих уровней даже корректно используемые функции шифрования становятся формальной защитой без реальной устойчивости к атакующему посреднику.