Безопасное использование сторонних компонентов
В процессе разработки ПО используются разные компоненты: операционные системы, среды выполнения контейнеров, фреймворки, библиотеки, расширения, плагины и темы. Кроме того, разработчики часто применяют инструменты коллег. Важно уделить внимание выбору такого ПО, чтобы не поставить под удар безопасность.
Многие приложения поддерживают установку дополнительных модулей, которые разрабатываются и поддерживаются отдельно от основного ПО. Прежде чем устанавливать такие модули, необходимо тщательно их изучить. Основное приложение может быть относительно безопасным, но это не гарантирует, что все его расширения также безопасны. Зачастую именно расширения связаны с наиболее критичными рисками.
Компания PatchStack сообщила, что в 2021 году на WordPress работало 43,2% всех веб-сайтов. При этом уязвимости плагинов и тем оставались одной из главных угроз для сайтов на WordPress. Только 0,58% уязвимостей безопасности было связано с ядром WordPress, остальные — со сторонними компонентами. Более того, 29% плагинов с критическими уязвимостями не получили патчи. Проблема в том, что сторонними компонентами пользуется большинство: в среднем на сайте WordPress установлено 18 различных компонентов.
Подавляющее большинство компонентов — это программы с открытым исходным кодом (Open Source Software, OSS). Сосредоточимся на советах по оценке OSS перед его использованием. Некоторые из этих советов также применимы к программам с закрытым исходным кодом.
Выбор компонентов
Фонд Open Source Security Foundation (OpenSSF) разработал краткое руководство по оценке OSS, которое может помочь в выборе компонентов. Они рекомендуют разработчикам определить потенциальные варианты и оценить их с точки зрения своих потребностей, прежде чем использовать зависимости или инструменты открытого ПО. Чтобы оценить потенциальную зависимость на предмет безопасности и устойчивости, ответьте на вопросы ниже.
Можно ли обойтись без добавления этой зависимости?
Решите, можно ли использовать уже существующую (возможно, косвенную) зависимость. Добавление каждой новой зависимости увеличивает поверхность атаки, поскольку взлом новой зависимости или ее транзитивных зависимостей может нарушить работу всей системы.
Какая версия ПО рассматривается?
Важно удостовериться, что вы анализируете основную версию ПО, а не персональный форк или форк, контролируемый злоумышленниками. Это помогает защититься от распространенной атаки «опечатки», или «тайпсквоттинга», когда злоумышленник создает вредоносный компонент с названием, почти полностью повторяющим название оригинального компонента.
- Проверьте название и ссылку на веб-сайт проекта.
- Изучите связь с форком на GitHub/GitLab.
- Выясните, не связан ли проект с каким-либо фондом (в этом случае у вас должна быть возможность получить доступ к официальному исходному коду с сайта фонда).
- Проверьте время создания проекта и его популярность.
Поддерживается ли ПО?
Если программное обеспечение не поддерживается, оно, скорее всего, небезопасно.
- Была ли значительная активность (например, коммиты) в течение последнего года?
- Когда был выпущен последний релиз (менее года назад)?
- Есть ли более одного сопровождающего, в идеале из разных организаций?
- Есть ли недавние релизы или анонсы от сопровождающего (сопровождающих)?
- Указывает ли обозначение версии на нестабильность (например, начинается с «0», включает «альфа» или «бета» и т. д.)?
Есть ли доказательства того, что разработчики работают над обеспечением безопасности?
- Выясните, заслужил ли проект значок Open Source Security Foundation (OpenSSF) Best Practices (или находится на пути к этому).
- Изучите информацию о проекте на https://deps.dev, включая его оценку по шкале OpenSSF Scorecards и все известные уязвимости.
- Узнайте, обновлены ли зависимости проекта.
- Проверьте, есть ли документация, объясняющая, почему проект безопасен. Наличие такой документации может свидетельствовать о внимании к безопасности.
- Разберитесь, включены ли автоматизированные тесты в конвейер CI и каково покрытие тестами?
- Убедитесь, что проект своевременно исправляет ошибки, особенно ошибки безопасности, и выпускает исправления безопасности для старых версий. Проверьте наличие версии LTS (Long Time Support).
- Посмотрите, используют ли разработчики механизмы безопасности систем работы с кодом, где это применимо.
- Изучите результаты аудитов безопасности и то, были ли устранены обнаруженные проблемы.
Легко ли безопасно использовать ПО?
- Проверьте, безопасна ли конфигурация по умолчанию. Если нет, избегайте использования таких конфигураций.
- Убедитесь, что интерфейс / API разработан так, чтобы его было безопасно использовать.
- Выясните, есть ли руководство по безопасному использованию программного обеспечения.
Существуют ли инструкции о том, как сообщать об уязвимостях?
См. Руководство по внедрению скоординированного процесса раскрытия информации об уязвимостях для проектов с открытым исходным кодом (OSS). Это может указывать на то, что разработчики открыты к обратной связи и готовы оперативно реагировать на обнаруженные уязвимости.
Насколько широко распространено ПО?
Широко распространенное ПО с большей вероятностью предложит полезную информацию о том, как использовать его безопасно, и больше специалистов будут заботиться о его безопасности. Проверьте, не является ли аналогичное название более популярным — это может свидетельствовать об атаке с использованием опечаток.
Как лицензируется ПО?
Лицензии технически не обеспечивают безопасность, но могут оказать на нее значительное влияние. Важно убедиться, что каждый компонент ПО имеет лицензию, особенно если речь идет о проектах с открытым исходным кодом (OSS). Широко используемые лицензии OSI обеспечивают открытость и прозрачность процесса разработки. Проекты, которые не предоставляют четкую информацию о лицензиях, могут поддерживать меньшие меры безопасности.
Важно иметь представление обо всех компонентах, составляющих ПО. Ведомость материалов программного обеспечения (Software Bill of Materials, SBOM) представляет собой структурированный перечень компонентов ПО. Многие экосистемы имеют специфические для них форматы SBOM. Существуют форматы, которые поддерживают произвольные экосистемы: Software Package Data Exchange (SPDX), Software ID (SWID) и CycloneDX. Если для компонента, который вы собираетесь использовать, доступен SBOM, эти данные могут дать ответы на некоторые из перечисленных выше вопросов. Полезно предоставлять SBOM пользователям вашего ПО: это поможет им лучше понимать состав и зависимости вашего продукта.
История: тайпсквоттинг от jeIlyfish и python3-dateutil
1 декабря 2019 года немецкий разработчик Лукас Мартини обнаружил, что две библиотеки Python в популярном репозитории PyPI (Python Package Index) используют технику опечаток для атак (тайпсквоттинг). Эти вредоносные пакеты похищали закрытые ключи SSH и GPG у разработчиков, которые их использовали. Вредоносный пакет jeIlyfish имитировал не вредоносный пакет jellyfish и наносил ущерб. Обратите внимание, что в названии вредоносного пакета третий символ — это прописная «I», а не строчная «l». Тот же злоумышленник также загрузил вредоносный пакет под названием python3-dateutil, который имитировал популярную библиотеку dateutil для Python3. Пакет python3-dateutil, который был загружен в PyPI всего за два дня до обнаружения, сам по себе не содержал вредоносного кода. Однако он зависел от другого вредоносного пакета – jeIlyfish, который был доступен в PyPI почти год. Обе библиотеки были удалены из репозитория в тот же день, когда было получено уведомление об их вредоносности.
Загрузка и установка компонентов
При загрузке и установке внешних компонентов ПО важно убедиться, что вы получаете их правильную версию:
Убедитесь, что имя компонента корректно
Одной из распространенных угроз является «тайпсквоттинг» – создание имени пакета или доменного имени, которое намеренно похоже на широко используемый компонент ПО. Злоумышленники используют такие имена для распространения вредоносных версий программного обеспечения. Компания Ohm & all в 2020 году обнаружила, что большинство вредоносных пакетов имитируют имена существующих пакетов с помощью тайпсквоттинга. Например:
- легко перепутать тире (-) и подчеркивание (_), единицу (1) и строчную букву L (l), ноль (0) и заглавную букву O (O). В некоторых менеджерах пакетов прописные и строчные буквы ASCII считаются разными; в таких ситуациях следует обращать внимание на регистр. Unicode предоставляет символы, которые выглядят точно так же, как ASCII, но представляют собой другой алфавит, например кириллический или греческий; в некоторых случаях их также можно использовать;
- проверьте, насколько популярен пакет. Как правило, более популярная версия является правильной. Сравните количество загрузок пакетов с похожими названиями. Те, что имеют меньшее количество загрузок, могут быть атаками тайпсквоттинга. Попробуйте воспользоваться поисковой системой, чтобы определить самый популярный пакет или домен. Однако не забывайте игнорировать все рекламируемые домены из поисковой системы: злоумышленники могут заплатить за рекламу своей вредоносной версии;
- проверьте дату выпуска пакета. Старый пакет часто является тем, который вы хотели получить.
Загрузите и установите ПО надежным способом
- загрузите ПО напрямую с официального сайта или с сайта распространения, которому вы доверяете (например, из репозитория вашего дистрибутива Linux или стандартного репозитория менеджера пакетов вашего языка программирования);
- для загрузки ПО используйте протокол HTTPS (с TLS), а не HTTP. Это гарантирует, что вы обращаетесь именно к тому сайту, который запрашивали;
- рассмотрите возможность загрузки ПО заранее, но установку и использование ее отложите на несколько дней, чтобы убедиться в отсутствии изменений. Так вы не сможете использовать поврежденную версию;
- избегайте pipe-to-shell (например, curl … | sh) для загрузки и установки ПО. При таком подходе вы не сможете отложить установку и проверить загруженный файл перед использованием. pipe-to-shell усложняет обнаружение и предотвращение атак на сайты с исходным кодом.
Однако, если использовать pipe-to-shell в ограниченном окружении, таком как контейнер или виртуальная машина с ограниченными привилегиями, и удалять все созданные исполняемые файлы после использования, риски значительно снижаются. Важно сосредоточиться на эффективном управлении рисками, а не на полном их избегании.
- в важных случаях старайтесь проверять, что пакет подписан цифровой подписью его предполагаемых создателей (или, по крайней мере, распространителей). ПО для проверки наличия цифровой подписи существует уже несколько десятилетий. В некоторых ситуациях предусмотрена автоматическая проверка того, что пакет действительно получен из определенного источника.
- будьте осторожны с зависимостью от возможности загрузки и установки компонентов во время выполнения из других (внешних) источников. Это широко распространенная практика для многих веб-приложений, особенно для их клиентских компонентов, таких как компоненты JavaScript и веб-шрифты. Однако существует риск того, что если этот источник станет недоступным (из-за атаки или просто потому, что поставщик прекратит его поддержку), ваша система также станет недоступной. Даже если поставщик — крупная организация, он все равно может принять решение прекратить поддержку того, от чего вы зависите.
Важно также обеспечить защиту от атаки «подмена зависимостей». Эта угроза касается систем, которые определяют список необходимых зависимостей и настроены на их получение из нескольких хранилищ. Такие системы часто зависят от определенного пакета, который разработчики предполагали получать из конкретного репозитория, обычно закрытого. Если не предусмотрено никаких мер для обеспечения получения пакета именно из предполагаемого источника, злоумышленник может создать вредоносный пакет с тем же именем в другом репозитории, обычно открытом, и обманом заставить систему использовать его вместо настоящего.
Злоумышленники могут использовать различные методы для увеличения вероятности успешной атаки, связанной с подменой зависимостей. Один из таких методов — использование большего номера для вредоносной версии, чтобы сделать пакет похожим на легитимный. Для минимизации рисков, связанных с подменой зависимостей, стоит применить следующие меры:
- использование единого источника — если все зависимости берутся из одного репозитория или реестра, подмена становится невозможной;
- четкое определение источников пакетов — можно явно указать, откуда должны быть получены конкретные пакеты, используя так называемые «контролируемые области»;
- расстановка приоритетов таким образом, чтобы сначала всегда обращаться к наиболее надежным каналам. Убедитесь, что менее надежные каналы никогда не отменяют более надежные;
- использование функции проверки на стороне клиента — привязка к зависимостям, также известная как привязка к версии, то есть требование использовать определенную известную версию. Для этого нужно установить требование криптографического хэш-значения, или цифрового отпечатка пакета. Другой подход — проверка целостности, позволяющая убедиться, что загруженный пакет идентичен тому, что был загружен в первый раз.
Обновление компонентов
На практике у вас будет много внешних компонентов, и их нужно будет время от времени обновлять. Иногда в одном из них обнаруживается уязвимость, и в этом случае необходимо быть готовым к оперативному обновлению.
- Используйте менеджеры пакетов, системы контроля версий (например, git), инструменты сборки и автоматизированные тесты, чтобы вы могли легко определить, какие версии каждого компонента у вас есть, и быстро обновить любой из них.
- Избегайте устаревших интерфейсов, чтобы максимально увеличить вероятность того, что вы сможете обновить внешний компонент, когда это будет необходимо.
- Ожидайте, что вам придется обновлять используемое ПО, включая базовую платформу.
- Не модифицируйте OSS и не создавайте свой собственный «локальный форк». Если уязвимость будет исправлена в более поздней версии OSS, то внедрить это исправление будет сложнее. Вместо этого, если вам нужно изменить OSS под свои нужды, работайте с исходным проектом OSS, чтобы ваши улучшения были включены в официальную версию. Тогда новые версии этого OSS, включая те, в которых исправлены уязвимости, также будут включать необходимые вам возможности.
- Поддерживайте внешние компоненты в относительно актуальном состоянии. Если они сильно устарели, заменить уязвимую версию на исправленную может быть очень сложно.
- Отслеживайте, не обнаружена ли в какой-либо из используемых вами версий ПО общеизвестная уязвимость.
История: Equifax
В широко используемой программе Apache Struts была обнаружена критическая уязвимость, которая была устранена 06.03.2017. Эта новость получила широкое освещение в компьютерной прессе.
Брокер данных Equifax был уведомлен об этой уязвимости компанией Apache, US CERT и Министерством внутренней безопасности США. Они предоставили Equifax инструкции по устранению уязвимости. Однако Equifax не выполнила своевременное обновление. «Спустя два месяца после обнаружения критической уязвимости в широко используемой программе Apache Struts, компания Equifax все еще не поставила патч на свои системы. Только 29 июля компания занялась устранением уязвимости. Злоумышленники воспользовались этой уязвимостью и получили доступ к базам данных Equifax, похитив информацию о потребителях. Это произошло 13 мая, более чем через два месяца после того, как Equifax должна была устранить уязвимость».
Equifax сообщила, что от взлома пострадали 145,5 миллиона американских клиентов, что составляет около 44 % населения США. Злоумышленники получили доступ к информации, которую преступники могут использовать для мошенничества в банках, компаниях, торгующих кредитными картами, страховых компаниях, компаниях по продаже мобильных телефонов и других предприятиях, уязвимых для мошенничества. Все 143 миллиона американских жертв подвергаются повышенному риску кражи личных данных, и этот риск будет сохраняться еще долгие годы. Те, кто пострадал от кражи личных данных, будут испытывать проблемы в течение нескольких месяцев, а то и лет, пока будут работать над восстановлением своего имени и кредитного рейтинга.
Важно обновлять не только компоненты, но и способы их использования.
По возможности следует избегать использования устаревших интерфейсов для взаимодействия с внешними компонентами. Иногда интерфейс устаревает из-за уязвимости в системе безопасности.
Если вы заменяете интерфейс, используемый другими компонентами, важно обеспечить длительный переходный период, в течение которого будут доступны как старый, так и новый интерфейсы. Это позволит проектам, которые зависят от старого интерфейса, плавно перейти на новый.
Использование криптографии
Термин «криптография» происходит от греческого выражения «тайное письмо». Это наука (или искусство) о преобразовании понятных данных в нечитаемый вид и их последующем восстановлении. Криптоанализ — это наука обратного преобразования зашифрованных данных без точного знания алгоритма. Поскольку многие активно пытаются атаковать криптографические системы, важно полагаться на проверенные и надежные методы.
В некоторых системах криптография является критически важной частью обеспечения безопасности. Она используется для защиты конфиденциальности данных при хранении и передаче, а также помогает подтвердить, что данные поступили от лица, обладающего соответствующим ключом, и удостовериться, что данные не были изменены.
В обычной разработке ПО при использовании криптографии следует соблюдать три ключевых правила.
Никогда не создавайте собственный криптографический алгоритм или протокол. Это узкоспециализированная задача, требующая глубокого знания высшей математики. Вместо этого найдите алгоритмы и протоколы, прошедшие публичную проверку авторитетными криптографами, и используйте их.
Никогда не реализуйте криптографические алгоритмы или протоколы самостоятельно, если есть альтернатива. Существует множество правил для реализации криптографических алгоритмов, которые не применяются в обычной разработке и потому неизвестны большинству программистов. Даже крошечные ошибки в реализации часто превращаются в серьезные уязвимости. Вместо этого используйте проверенные готовые реализации.
Помните: криптографические системы иногда взламывают. Алгоритмы и протоколы со временем ослабевают. Убедитесь, что используемые вами методы до сих пор считаются стойкими, и будьте готовы заменить их при необходимости.
При выборе криптографической библиотеки выбирайте ту, которая прошла публичное рецензирование и предоставляет интуитивно понятный API, снижающий риск ошибок. Иначе вы рискуете внести уязвимости из-за дефектов в самой библиотеке или ее неправильного применения.
Криптоаналитики постоянно ищут способы взлома алгоритмов, а криптографы работают над противодействием этим атакам. Исторически алгоритмы создаются, используются какое-то время, а в итоге взламываются. Поэтому, прежде чем выбрать что-либо в криптографии, проверьте, не является ли такое решение слабым или уже скомпрометированным.
Симметричные алгоритмы (с общим ключом)
Симметричный алгоритм шифрования принимает на вход данные, называемые открытым текстом, и ключ, и выводит зашифрованные данные — шифротекст. Он также работает в обратном направлении: используя шифротекст и тот же ключ, можно восстановить исходный открытый текст.
Ключевая особенность симметричного шифрования заключается в том, что один и тот же ключ используется как для шифрования, так и для расшифрования. Это значит, что любой, кто расшифровывает данные, должен иметь доступ к этому ключу. Хранить и передавать ключ важно с особой осторожностью.
Большинство современных симметричных алгоритмов работают очень быстро, часто с аппаратным ускорением, и лежат в основе многих криптографических систем. На данный момент самым распространенным симметричным алгоритмом является Advanced Encryption Standard (AES).
Некоторые широко распространенные в прошлом симметричные алгоритмы сегодня считаются небезопасными из-за многочисленных уязвимостей или недостаточной стойкости: DES, RC4, 3DES, Blowfish.
Многие симметричные алгоритмы, включая AES, являются блочными. При использовании блочного алгоритма необходимо корректно выбрать режим шифрования:
- Electronic Code Book — ECB. По сути является отладочным или тестовым режимом алгоритма. В ECB один и тот же блок данных всегда даёт одинаковый результат шифрования. Это катастрофично, поскольку раскрывает слишком много информации о данных, которые должны быть зашифрованы. Никогда не используйте режим ECB в рабочих окружениях!
- Cipher Block Chaining — CBC. Требует последовательной обработки блоков, что замедляет работу на многопроцессорных системах. Кроме того, системы, использующие CBC, могут быть уязвимы к определенным атакам при отсутствии отдельной проверки целостности данных. Поэтому сегодня режим CBC обычно не рекомендуется
- Galois/Counter Mode — GCM. Работает быстро, поддерживает параллелизм и включает встроенную проверку целостности, которая обнаруживает подмену данных или неверный ключ. GCM — надежный выбор для современных систем.
Асимметричные алгоритмы (с открытым ключом)
В системах с открытым ключом (асимметричных системах) используется пара ключей: закрытый ключ, который известен только владельцу, и открытый ключ, который можно свободно распространять. Ключи связаны между собой, но выполняют разные роли — отсюда название «асимметричная криптография». В таких системах необходимо строго охранять закрытый ключ от разглашения.
- Шифрование. Любой может зашифровать данные, используя открытый ключ, но расшифровать их сможет только обладатель соответствующего закрытого ключа. Алгоритмы шифрования с открытым ключом обычно работают медленно, поэтому на практике открытым ключом шифруют лишь симметричный сеансовый ключ, а основные данные шифруются быстрым симметричным алгоритмом.
- Цифровые подписи. С помощью алгоритма с открытым ключом и своего закрытого ключа можно создать цифровую подпись. Любой, у кого есть открытый ключ, способен проверить, что подпись была создана владельцем соответствующего закрытого ключа.
- Обмен ключами. Некоторые алгоритмы с открытым ключом позволяют двум сторонам безопасно сформировать общий секретный ключ так, чтобы пассивный наблюдатель не смог его вычислить.
Широко используемым алгоритмом с открытым ключом является RSA, который может применяться для шифрования, цифровых подписей и обмена ключами. Однако не реализуйте RSA самостоятельно. RSA основан на возведении больших чисел в степень, что может создать у разработчиков ложное впечатление простоты. На практике крайне легко реализовать RSA с уязвимостями.
Для обеспечения приемлемого уровня безопасности длина ключей RSA должна быть значительно больше, чем у симметричных ключей:
1024-битный RSA ≈ 80-битный симметричный ключ → слишком мал и небезопасен,
2048-битный RSA ≈ 112-битный симметричный ключ → едва допустим (NIST разрешает использование до 2030 года),
3072-битный RSA ≈ 128-битный симметричный ключ → рекомендуется для текущих внедрений,
15360-битный RSA ≈ 256-битный симметричный ключ.
С увеличением длины ключа RSA также замедляется его работа, что является еще одной причиной, по которой рекомендуется по возможности избегать RSA.
Криптография на эллиптических кривых (Elliptic Curve Cryptography, ECC) – это семейство алгоритмов, основанных на сложной математике эллиптических кривых. Ключевое преимущество ECC в том, что она обеспечивает сопоставимую с RSA криптостойкость при значительно меньшей длине ключей.
Исторически внедрению ECC мешали патенты, но большинство из них уже истекли, и сегодня криптография на эллиптических кривых получила широкое распространение. Широко используемые алгоритмы на основе эллиптических кривых включают X25519 — для обмена ключами, EdDSA — для цифровых подписей, ECIES — связанный протокол, комбинирующий обмен ключами на эллиптических кривых с симметричным шифрованием.
Digital Signature Standard (DSS) — стандарт NIST (FIPS 186-5) для создания криптографических цифровых подписей. Он поддерживает несколько базовых алгоритмов: алгоритм цифровой подписи RSA, алгоритм цифровой подписи на эллиптических кривых (ECDSA) и алгоритм цифровой подписи на кривых Эдвардса (EdDSA).
Существуют также различные алгоритмы обмена ключами. Самый старый — алгоритм обмена ключами Диффи-Хеллмана. Более современная версия на основе эллиптических кривых — Elliptic Curve Diffie-Hellman (ECDH).
Критически важно использовать проверенные реализации (а не реализовывать эти алгоритмы самостоятельно) и тщательно проверять параметры. Длина ключа особенно важна для безопасности. Алгоритмы на эллиптических кривых обеспечивают сравнимую стойкость при гораздо более коротких ключах. Рекомендуемые длины ключей можно найти в документе NIST «Recommendation for Key Management: Part 1 – General».
Алгоритмы с открытым ключом легко использовать неправильно или реализовать с ошибками. Применяйте авторитетные библиотеки, внимательно проверяйте параметры и выбирайте соответствующую длину ключа для выбранного алгоритма.
Криптографические хеш-функции
Некоторым приложениям требуется односторонняя криптографическая хеш-функция – алгоритм, который принимает произвольный объем данных и генерирует число фиксированной длины с особыми свойствами:
- Устойчивость к прообразу. Задача подбора данных с заданным значением хеша должна быть практически невыполнимой для злоумышленника.
- Устойчивость ко второму прообразу. Задача создания других (измененных) данных с тем же хешем, что и конкретное исходное сообщение, должна быть практически невыполнимой для злоумышленника.
- Устойчивость к коллизиям. Задача нахождения любых двух разных сообщений с одинаковым хешем должна быть практически невыполнимой для злоумышленника.
Основная идея криптографических хешей заключается в том, что они являются «односторонними»: по хешу, как правило, невозможно восстановить исходные данные. Криптографические хеши полезны сами по себе, а также используются как компоненты более сложных криптографических систем.
Некоторые устаревшие хеш-алгоритмы известны как скомпрометированные, и их не стоит использовать: MD4, MD5, SHA-0. Эти алгоритмы больше не обеспечивают необходимой устойчивости к атакам.
Семейство SHA-2 (включая SHA-256 и SHA-512) и алгоритм SHA-3 широко используются и считаются безопасными. SHA-3 был разработан, в том числе из-за опасений, связанных с SHA-2, однако публично подтвержденных успешных атак на SHA-2 не зафиксировано.
SHA-1 – это устаревший алгоритм, который не следует использовать в новых системах, а текущие реализации на его основе рекомендуется как можно быстрее заменить. NIST объявил SHA-1 нерекомендуемым еще в 2011 году, так как он практически скомпрометирован и больше не считается криптографически стойкой хеш-функцией.
В большинстве сценариев переход на SHA-2 или SHA-3 не представляет проблемы. Однако есть одно исключение: широко распространенная система контроля версий git в своей базовой реализации фундаментально зависит от SHA-1. Известные на сегодняшний день атаки на SHA-1 не представляют угрозы для обычного использования git. Кроме того, начиная с 2020 года, git применяет модифицированную, более стойкую версию SHA-1, которая нейтрализует основные уязвимости алгоритма в контексте работы git. Тем не менее, поскольку методы атак постоянно совершенствуются, сохраняются серьезные сомнения в долгосрочной безопасности SHA-1 даже в рамках git.
Криптографически стойкий генератор псевдослучайных чисел (CSPRNG)
Многие криптографические алгоритмы полагаются на секретные значения, которые злоумышленник не должен уметь предсказывать — такие значения называются «криптографически стойкими». Это, например, закрытые ключи, одноразовые числа (nonce), идентификаторы сессий и подобные данные. Если атакующий сможет угадать эти значения (включая прошлые или будущие), многие системы окажутся уязвимыми.
Проблема отчасти историческая: сегодня в большинстве языков программирования слово «random» (случайный) обычно означает, что функция не является криптографически стойкой. Ранние компьютеры часто использовались для моделирования (особенно методом Монте-Карло), где требовалось многократно генерировать случайные числа. Для таких задач важно было иметь возможность воспроизвести ту же последовательность, чтобы повторить эксперимент. Внутри такие функции часто реализовывались алгоритмами вроде линейного конгруэнтного генератора (Linear Congruential Generator, LCG) и инициализировались значениями вроде текущей даты или времени, которые злоумышленник может легко предсказать.
Поскольку это было одним из первых применений компьютеров, почти во всех языках программирования сложилось соглашение: слово «random» означает генерацию последовательности чисел, которую можно легко воспроизвести при необходимости. Другими словами, «случайный» в контексте языков программирования обычно означает предсказуемо случайный, что не подходит для криптографии или систем безопасности.
В криптографии и задачах безопасности необходимо применять криптографически стойкий генератор псевдослучайных чисел (Cryptographically Secure Pseudorandom Number Generator, CSPRNG). Надежный CSPRNG не позволяет атакующему предсказать следующее значение, даже если известны предыдущие результаты, и защищает ранее сгенерированные значения, даже если внутреннее состояние генератора было скомпрометировано. Обычно в названии таких реализаций есть слова secure или crypto.
В документации часто упоминаются общепринятые алгоритмы CSPRNG, такие как Yarrow, Fortuna, ANSI X9.17 (совместимый с любым блочным шифром), а также алгоритмы стандарта NIST SP 800-90A: Hash_DRBG, HMAC_DRBG и CTR_DRBG.
Ни в коем случае не используйте алгоритм Dual_EC_DRBG — он считается скомпрометированным и небезопасным.
Так выглядит вызов обычного (предсказуемого) генератора и криптографически стойкого генератора в разных языках:
| Язык | Обычный (предсказуемый) генератор | Криптографически стойкий генератор |
|---|---|---|
| JavaScript | Math.random | window.crypto.getRandomValues или crypto.randomBytes |
| Python | random | os.urandom |
| Ruby | rand (или Random.rand) | SecureRandom.rand |