Каждые несколько лет среди специалистов по безопасности поднимаются дискуссии о вреде JS-криптографии. Сейчас они возобновились. Что стало поводом и почему у некоторых специалистов такое предубеждение к криптографическим операциям в браузере? Попробуем разобраться.

Критика JavaScript-криптографии


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

  • Излишнее использование JS-криптофункций там, где достаточно SSL/TLS. Например, создание собственных криптопротоколов для передачи парольных хэшей от клиента на сервер в процессе аутентификации. Или генерация AES-ключа для каждой пользовательской заметки на сервере, чтобы зашифрованные данные не были доступны никому постороннему, даже серверу.
  • Передача JS-кода в браузер не может быть осуществлена безопасным способом, если нет доверия к серверу (проблема курицы и яйца). Другими словами, если вы не доверяете серверу передачу пароля по SSL/TLS, то нет причин доверять ему передачу криптографического JS-кода к клиенту. Тот же злоумышленник, который потенциально может перехватить пароли до шифрования SSL/TLS, может и скомпрометировать JS-код, что сделать очень легко внедрением одного скрипта. Конечно, криптобиблиотеки можно передать по SSL/TLS, но в таком случае они больше не нужны.
  • Браузерный JavaScript не создан для криптографии вплоть до того, что он якобы по своей природе враждебен приложениям информационной безопасности, в нём слишком много «простых» уязвимостей. Конечно, в серьёзном криптографическом ПО и библиотеках тоже находят уязвимости, но это единичные редкие случаи. На поиск таких уязвимостей уходит много сил и времени, в то время как баги в JS-коде бывают тривиальны.
  • Ложное чувство безопасности. Применение ненадёжной JS-криптографии удерживает пользователей от использования действительно качественных и безопасных криптографических инструментов.

Претензии выдвигаются именно к криптографическим операциям в браузере, в то время как выполнение криптографического JS-кода за пределами браузера не считается настолько опасным/неправильным.

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

Изменчивая среда выполнения означает, что каждое выполнение JS-кода выполняется по сути после его переустановки. Нельзя гарантировать ни стабильности самого кода, ни постоянного окружения.

Ещё одна проблема браузеров — тотальное кэширование всего контента, что не даёт возможности выполнения криптографического кода в чистом окружении.

Современные практики


В реальности современного веба большая часть криптографических функций уже реализована на JavaScript. Поддерживаются основные примитивы системного программирования, необходимые для криптографии, в том числе генератор случайных чисел. Например, через Math.random():

function getRandomInt(max) {
 return Math.floor(Math.random() * max);
}

console.log(getRandomInt(3));
// Expected output: 0, 1 or 2

console.log(getRandomInt(1));
// Expected output: 0

console.log(Math.random());
// Expected output: a number from 0 to <1

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

В последнее десятилетие в вебе реализовано множество криптосистем, в том числе приложения со сквозным шифрованием, P2P-системы с разделением секрета, финансовые системы на блокчейне, протоколы доказательства с нулевым разглашением (zero-knowledge proof, ZKP). Разработан устойчивый к прослушиванию протокол парольной аутентификации (SRP) на основе обмена ключами PAKE и другие системы, в том числе такие, безопасность которых математически доказана. Все они полагаются на JS-криптографию в браузере и считают это нормальным. Хотя критики называют это криптографическим театром (по аналогии с театром безопасности, где существует только иллюзия безопасности).

В конце концов, загрузка кода с сервера не слишком отличается от загрузки программных пакетов из репозитория. У этих каналов одинаковый метод защиты — HTTPS:

«Если [менеджер пакетов] поддерживает HTTPS и правильно проверяет сертификаты, дистрибутив может установить репозитории или зеркала, поддерживающие передачу данных по HTTPS. Это не защитит от вредоносного зеркала, но предотвратит атаку MiTM от постороннего лица» — из статьи «Взгляд в зеркало: атаки на пакетные менеджеры», CCS '08: Proceedings of the 15th ACM conference on Computer and communications security, стр. 565–574, doi: 10.1145/1455770.1455841

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

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

На самом деле не существует однозначного на вопрос о безопасности веб-криптографии. В некоторых случаях веб-приложения с поддержкой криптографии безопаснее, чем аналогичные нативные приложения без криптографии.

Комментарии (6)


  1. Number571
    14.07.2023 16:54
    +17

    Поддерживаются основные примитивы системного программирования,
    необходимые для криптографии, в том числе генератор случайных чисел.
    Например, через Math.random()

    Что? Math.random - это ГПСЧ, а не КСГПСЧ.

    Note: Math.random() does not
    provide cryptographically secure random numbers. Do not use them for
    anything related to security. Use the Web Crypto API instead, and more
    precisely the window.crypto.getRandomValues() method.

    Источник: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random


  1. x88
    14.07.2023 16:54
    +2

    У браузерных расширений и скриптов, криптография не самое слабое место. Более распостранены XSS, hijacking (в следствие выполнения кода в пользовательской среде). В зависимости от сценария, что-то можно упаковать в wasm, но вот если пользователь установил зловредное расширение, то inject и выполнение произвольного кода может производиться на любой странице.


  1. Opaspap
    14.07.2023 16:54
    +3

    Браузерный JavaScript не создан для криптографии

    А для чего создан этот API ?
    https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API


    1. SuperCat911
      14.07.2023 16:54

      Math.random никто не использует. В любом браузере сейчас можно так:

      const array = new Uint32Array(10);
      window.crypto.getRandomValues(array);
      
      console.log("Your lucky numbers:");
      for (const num of array) {
        console.log(num);
      }

      Источник тут: https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues

      Причем getRandomValues реализована даже в IE11. https://caniuse.com/getrandomvalues


  1. jasiejames
    14.07.2023 16:54
    +2

    Я так и не понял о чём именно статья? Наверное я тупой  ¯\_(ツ)_/¯

    Насколько опасна JavaScript-криптография?

    Так насколько она опасна? Вступление есть, концовка есть, а где собственно всё тело статьи?


    1. qw1
      14.07.2023 16:54

      Статья в корпоративном блоге компании, занимающейся PKI.
      Естественно, они напишут — "не изобретайте велосипеды, а приходите к нам, мы вам сгенерим сертификаты" (и тов. майору тоже заодно).