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

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

Основные ошибки разработчиков, которые имеют дело с Crypto Make

Перечисленные здесь наиболее распространенные ошибки (по мнению нас в Cossack Labs) не связаны напрямую с криптографическими процессами и шифрованием, но их совершение в лучшем случае делает криптографию бесполезной, приводит к уязвимостям, открывает систему для эксплойтов и может привести к сбоям в работе или DoS. Небольшая внимательность имеет большое значение, и следующие практики должны служить контрольным списком того, чего не следует делать в своем программном обеспечении и к чему это приведет, если вы это сделаете.

Буферизация копии без проверки размера ввода (классическое переполнение буфера)

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

Переполнение буфера часто может использоваться для выполнения произвольного кода, который обычно выходит за рамки неявной политики безопасности программы. Это часто можно использовать для подрыва любой другой службы безопасности. А переполнение буфера приводит к сбоям и открывает программу для вредоносных внешних действий, таких как DoS или перевод программы в бесконечный цикл.

Профилактика / смягчение:

  • Дважды проверьте, соответствует ли размер буфера указанному вами.
  • При использовании функций, которые принимают количество байтов для копирования (например, strncpy ()), помните, что если размер целевого буфера равен размеру исходного буфера, он не может завершать строку NULL;
  • Проверяйте границы буфера при доступе к буферу в цикле. Также убедитесь, что вы не пишете за пределы выделенного места;
  • Для любых проверок безопасности, которые выполняются на стороне клиента, убедитесь, что эти проверки дублируются на стороне сервера, чтобы избежать CWE-602. Злоумышленники могут обойти проверки на стороне клиента, изменив значения после выполнения проверок или изменив клиента, чтобы полностью удалить проверки на стороне клиента.

Доступ к буферу с неправильным значением длины

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

Профилактика / смягчение:

Используйте правила предотвращения / смягчения последствий уязвимости классического переполнения буфера.

Использование потенциально опасных функций

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

1) использование неслучайного IV с режимом CBC блочного шифра типа AES,

2) использование недостаточной энтропии / малого / одинакового / предсказуемого начального числа для ГПСЧ,

3) использование криптографически слабого ГПСЧ.

Профилактика / смягчение:

Определите список запрещенных функций API и запретите разработчикам (или себе) использовать эти функции (иногда вам придется придумывать более безопасные альтернативы). В некоторых случаях инструменты автоматического анализа кода или компилятор могут получить указание обнаружить использование запрещенных функций, таких как включаемый файл banned.h из Microsoft SDL ».

Прокат собственной криптовалюты

Может возникнуть соблазн разработать собственную схему шифрования в надежде затруднить взлом злоумышленников. Однако такая самодельная криптография - «долгожданный» знак для потенциальных злоумышленников.

Профилактика / смягчение:

Выберите проверенный алгоритм, одобренный и рекомендованный экспертами в области криптографии, и выберите хорошо протестированные реализации (исходный код должен быть доступен для анализа). Мы можем быть предвзятыми, но рекомендуем использовать Themis для шифрования, поскольку это хорошо протестированная модульная криптографическая библиотека с открытым исходным кодом, лицензированная Apache 2, которая в настоящее время использует OpenSSL в качестве источника своих криптографических примитивов.

Неправильный расчет размера буфера

В языках, где управление памятью является обязанностью программиста (например, C), существует много возможностей для ошибки. Если размер буфера вычислен неправильно, буфер может быть слишком маленьким, чтобы содержать данные, которые программист намеревается записать, даже если ввод был правильно проверен. Любое количество проблем может привести к неправильному вычислению, но в конце концов вы столкнетесь с переполнением буфера.

Профилактика / смягчение:

  • Если вы выделяете буфер для преобразования, преобразования или кодирования ввода, убедитесь, что вы выделяете достаточно памяти для обработки максимально возможного кодирования. Например, в подпрограмме, которая преобразует символы «&» в «» для кодирования объекта HTML, вам понадобится выходной буфер, который как минимум в 5 раз больше входного буфера;
  • Обратите особое внимание на несоответствия в размере байта, точность, различие между знаками и без знака, усечение, преобразование и приведение типов между типами, вычисления «не числа» и то, как ваш язык обрабатывает числа, которые слишком велики или слишком малы для его лежащее в основе представление. Помните о 32-битных, 64-битных и других потенциальных различиях, которые могут повлиять на числовое представление;
  • При обработке структурированных входящих данных, которые содержат поле размера, за которым следуют необработанные данные, убедитесь, что вы выявляете и устраняете любые несоответствия между полем размера и фактическим размером данных;
  • При распределении памяти, в которой используются метки для обозначения конца структуры данных (например, байты NULL в строках), убедитесь, что вы также включили метку в свой расчет общего объема памяти, который должен быть выделен;
  • Используйте sizeof () для соответствующего типа данных, чтобы избежать CWE-467 (Использование sizeof () для типа указателя);
  • Внимательно изучите предупреждения компилятора и устраните проблемы, которые могут повлиять на безопасность, такие как несоответствие подписанных и неподписанных операций с памятью или использование неинициализированных переменных. Даже если слабое место редко можно использовать, единичный сбой может привести к компрометации всей системы.

Неправильная проверка индекса массива

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

  • Использование индекса за пределами массива очень вероятно приведет к повреждению соответствующей памяти и, возможно, инструкций, что приведет к сбою, если значения находятся за пределами допустимой области памяти.
  • Если данные повреждены, система продолжит работу с неправильными значениями.
  • Использование индекса за пределами массива также может запускать операции чтения или записи за пределами массива или операции с неправильными объектами. Это может привести к раскрытию или изменению конфиденциальных данных.
  • Если злоумышленник может эффективно управлять памятью, возможно, будет возможно выполнить произвольный код (как при стандартном переполнении буфера) даже без использования больших входных данных, если можно контролировать точный индекс.
  • Единичный сбой приводит к переполнению (CWE-788) или опустошению (CWE-786) индекса массива. Последствия будут зависеть от типа операции, выполняемой вне пределов, но они могут раскрыть конфиденциальную информацию, вызвать сбой системы или, возможно, привести к выполнению произвольного кода.

Профилактика / смягчение:

  • Используйте структуру проверки ввода, такую ​​как Struts или OWASP ESAPI Validation API (т.е. ESAPI позволяет использовать ESAPI :: getValidator () - ›getValidInput (…)). Если вы используете Struts, помните о недостатках, раскрытых в CWE-101.
  • Будьте особенно осторожны при проверке всех входных данных при вызове кода, который пересекает языковые границы (то есть от интерпретируемого языка к машинному коду), поскольку это может создать неожиданное взаимодействие между этими границами.
  • Убедитесь, что вы не нарушаете никаких ожиданий от языка, с которым вы взаимодействуете. Например, даже несмотря на то, что Java может быть невосприимчивой к переполнению буфера, предоставление большого аргумента при вызове собственного кода может все же вызвать переполнение.

Строка неконтролируемого формата

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

Профилактика / смягчение:

  • Убедитесь, что все функции форматирования строк передаются статической строкой, которой не может управлять пользователь, и что правильное количество аргументов также всегда отправляется этой функции. По возможности используйте функции, которые не поддерживают оператор% n в строках формата.
  • Обратите внимание на предупреждения компиляторов и компоновщиков - они могут предупредить вас о неправильном использовании.

Целочисленное переполнение или перенос

Целые числа - это не Чак Норрис, поэтому у них есть свои пределы. И машины не могут считать до бесконечности, даже если иногда кажется, что им требуется так много времени, чтобы выполнить важную задачу. Когда программисты забывают, что компьютеры не занимаются математикой, как люди, происходят плохие вещи, в том числе все, начиная от ошибочных расчетов цен, бесконечных циклов и заканчивая сбоями и т. Д.

Профилактика / смягчение:

  • Выполните проверку ввода для любого числового ввода, убедившись, что он находится в ожидаемом диапазоне.
  • Обеспечьте соблюдение правил, которые гарантируют, что входные данные соответствуют как минимальным, так и максимальным требованиям для ожидаемого диапазона.
  • По возможности используйте целые числа без знака. Это упрощает проверку работоспособности целочисленных переполнений. Если вам абсолютно необходимо использовать целые числа со знаком, убедитесь, что ваша проверка диапазона включает как минимальные, так и максимальные значения.
  • Здесь также применяются правила предотвращения / смягчения ошибок при неправильном вычислении размера буфера .

Игнорирование предупреждений компилятора

Популярные компиляторы разрабатываются десятилетиями (т.е. первый выпуск gcc датируется мартом 1987 года) с помощью сотен участников. Это означает, что в большинстве случаев проблемы безопасности могут быть обнаружены с помощью предупреждений компилятора. Но их часто игнорируют.

Профилактика / смягчение:

  • Скомпилируйте свой код, используя самый высокий уровень предупреждений, доступный для вашего компилятора, и устраните предупреждения, изменив код.
  • Используйте инструменты статического и динамического анализа для обнаружения и устранения дополнительных недостатков безопасности.

Обычные методы шифрования, которым следует следовать

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

Избегайте использования паролей в качестве ключей шифрования

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

Решение. Используйте действительно случайный ключ шифрования / дешифрования, а не ключ, детерминированно сгенерированный из пароля / парольной фразы. Мы рекомендуем использовать PBKDF2 (который мы включили в Themis), который использует итеративное хеширование (по строкам H (H (H (… .H (пароль)…))), чтобы замедлить поиск по словарю.

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

Будьте осторожны при объединении нескольких строк перед хешированием; вместо этого используйте комбинации хешей каждой строки

Конкатенация оставляет неоднозначную индикацию пробела между двумя строками. Например:

встроенный || безопасно = встроенный || небезопасно

автомобиль || умение = автомобили || убить

Иными словами, хэш H (S || T) не идентифицирует однозначно строки S и T. Следовательно, злоумышленник может изменить разделение между двумя строками, не меняя хеш.

Например, если Алиса хотела отправить две строки «встроенная» и «безопасно», злоумышленник мог бы изменить их на строки «встроено» и «небезопасно», не аннулируя хэш. Подобные проблемы возникают при применении цифровой подписи или кода аутентификации сообщения к конкатенации строк.

Вместо использования простой конкатенации используйте однозначно декодируемое кодирование. Например, вместо вычисления H (S || T) вычислите H (length (S) || S || T), где length (S) - 32-битное значение, обозначающее длину S в байтах. Другое решение - использовать H (H (S) || H (T)) или даже H (H (S) || T).

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

Использование одного ключа для нескольких целей может открыть его для различных тонких атак. Выберите ключ для одной цели и используйте его только для этой цели. Если вам нужно выполнять обе функции, сгенерируйте две пары ключей, одну для подписи, а другую для шифрования / дешифрования. Точно так же с симметричной криптографией вы должны использовать один ключ для шифрования и отдельный независимый ключ для аутентификации сообщений. Не используйте повторно один и тот же ключ для обеих целей.

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

Используйте принципы и рекомендации по управлению ключами, описанные в нашей Themis GitHub Wiki.

Вести подробные журналы и контрольные журналы

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

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

Этот момент очень важен, даже если он выходит за пределы строго криптографической плоскости. Мы повторим, что использование сильной криптографии ДЕЙСТВИТЕЛЬНО гарантирует защиту от всех известных теоретических атак, но НЕ БУДЕТ гарантировать высокий уровень безопасности сложной компьютерной системы от всех возможных угроз реального мира.

Дополнительную образовательную и развлекательную информацию о правилах безопасности данных, не связанных с криптографией, см. Также в нашей Средней статье о методах безопасности, не связанных с криптографией.

Это наш взгляд на эту тему. Если у вас есть что добавить, чтобы расширить список ошибок или передовых методов, свяжитесь с нами через @CossackLabs или по электронной почте.