Хабрахабр

Статический анализатор кода PVS-Studio как защита от уязвимостей нулевого дня

Статический анализатор кода PVS-Studio как защита от уязвимостей нулевого дня

Угроза нулевого дня (англ. zero day) – это термин, обозначающий уязвимости, допущенные при разработке, которые еще не были обнаружены. Такие уязвимости могут использоваться злоумышленниками, что в итоге затронет и репутацию компании. Перед разработчиками стоит задача максимально сократить количество дефектов в коде, которые могут стать причиной такой уязвимости. Одним из инструментов, помогающих выявить дефекты безопасности, является статический анализатор кода PVS-Studio для C, C++, C#, Java.

Угроза нулевого дня

Угроза нулевого дня — термин, обозначающий бреши и уязвимости, которые были допущены разработчиками, но при этом еще не были обнаружены. До тех пор, пока уязвимость не будет устранена, она может использоваться для доступа к сетям, удаленному управлению компьютером, манипуляций с данными и т.п. Такое название термина устоялось по причине того, что у разработчиков нет ни дня на исправление дефекта, так как о нём пока никто не знает. В свое время от такого рода уязвимостей пострадали такие крупные компании и ПО, как Adobe, Windows, Tor browser и многие другие.

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

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

Однако есть способы уменьшить вероятность возникновения такой угрозы в своем проекте, и далее мы их обсудим, но для начала немного теории. Проблема этой угрозы в том, что от нее невозможно защититься на 100%, так как тяжело защищаться от того, о чем ты пока не знаешь.

Статический анализ

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

CVE и CWE

Common Vulnerabilities and Exposures (CVE) – база данных программных ошибок, которые могут быть использованы злоумышленниками. CVE была создана для того, чтобы упорядочить известные дефекты программ. В большинстве инструментов информационной безопасности использовались собственные базы данных и имена, и, дабы устранить этот хаос и добавить совместимость с различными инструментами, организация MITRE в 1999 году создала CVE. Однако CVE оказалось недостаточно для оценки безопасности кода. Для этого требуется что-то точнее, с подробным описанием проблем и менее грубое, чем она. Поэтому и была создана база Common Weakness Enumeration (CWE), которая удовлетворяет этим требованиям. Если ошибка есть в списке CWE, то есть вероятность, что она приведет к появлению уязвимости, которой может воспользоваться злоумышленник, и попасть в список CVE. Для наглядности можно посмотреть на приведенную ниже диаграмму Эйлера.

CVE, CWE

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

Такие анализаторы можно расценивать как SAST решение. С приходом в мир разработки списков CVE и CWE многие инструменты информационной безопасности позаботились об их поддержке, в том числе и статические анализаторы. SAST (Static Application Security Testing) позволяет разработчикам находить уязвимости в исходном коде приложения уже на ранних этапах жизненного цикла разработки программного обеспечения.

Анализатор, классифицирующий свои ошибки согласно CWE, может подсказать, где скрывается возможная уязвимость. Использовать SAST при разработке – еще один вариант минимизирования вероятности появления угрозы нулевого дня. И исправляя эти ошибки, разработчик делает свое приложение надежнее и уменьшает вероятность наступления 0-day угрозы.

Для демонстрации возможностей в борьбе с уязвимостями остановимся на инструменте PVS-Studio. Существуют различные инструменты статического тестирования защищенности. Рассмотрим несколько примеров. Предупреждения этого анализатора могут классифицироваться как CWE.

Предупреждение PVS-Studio: CWE-561: Dead Code (V3021).

public string EncodeImage(....)
if (string.IsNullOrWhiteSpace(inputPath)) { throw new ArgumentNullException("outputPath"); } ....
}

В этом коде по невнимательности допустили опечатку. В двух условиях if проверяется одна и та же переменная. Судя по генерируемому исключению, во втором условии должна проверяться переменная outputPath. В результате часть кода является недостижимой.

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

В своё время эта ошибка стала причиной появления уязвимости в операционной системе iOS.

1. Описание уязвимости CVE-2014-1266: The SSLVerifySignedServerKeyExchange function in libsecurity_ssl/lib/sslKeyExchange.c in the Secure Transport feature in the Data Security component in Apple iOS 6.x before 6. 0. 6 and 7.x before 7. 0. 6, Apple TV 6.x before 6. 9.x before 10. 2, and Apple OS X 10. 2 does not check the signature in a TLS Server Key Exchange message, which allows man-in-the-middle attackers to spoof SSL servers by using an arbitrary private key for the signing step or omitting the signing step. 9.

static OSStatus
SSLVerifySignedServerKeyExchange(SSLContext *ctx, bool isRsa, SSLBuffer signedParams, uint8_t *signature, UInt16 signatureLen)
{ OSStatus err; .... if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; .... fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err;
}

Из-за двойного goto также возникает ситуация с недостижимым кодом. Вне зависимости от условий в операторах if будет выполнен второй оператор goto. Это приводит к тому, что проверка подписи не происходит. Функция возвращает 0, который обозначает, что с подписью все хорошо, и далее программа получает ключ с сервера, даже если с подписью есть проблемы. Этот ключ нужен для шифрования данных при передаче.

Поэтому нет смысла рассуждать, насколько опасна та или иная ошибка, классифицируемая как CWE. Последствия такой простой ошибки оказались весьма серьезны. Её просто следует исправить, тем самым сделав код более безопасным.

Он выдал бы здесь сразу два CWE предупреждения: Кстати, описанная ошибка легко могла бы быть выявлена анализатором PVS-Studio.

Давайте рассмотрим ещё один пример. В далеком 2012 году стало известно о проблеме безопасности в MySQL, при которой злоумышленник мог войти в базу данных MySQL. Далее я приведу отрывок кода, который послужил этому причиной.

1.x before 5. Описание CVE-2012-2122: sql/password.c in Oracle MySQL 5. 63, 5. 1. 5. 5.x before 5. 6.x before 5. 24, and 5. 6, and MariaDB 5. 6. 1. 1.x before 5. 2.x before 5. 62, 5. 12, 5. 2. 3. 3.x before 5. 5.x before 5. 6, and 5. 23, when running in certain environments with certain implementations of the memcmp function, allows remote attackers to bypass authentication by repeatedly authenticating with the same incorrect password, which eventually causes a token comparison to succeed due to an improperly-checked return value. 5.

typedef char my_bool;
my_bool
check_scramble(const char *scramble_arg, const char *message, const uint8 *hash_stage2)
{ .... return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}

Тип возвращаемого значения функции memcmp — int, а тип возвращаемого значения функции check_scramble — my_bool, фактически — char. В результате происходит неявное приведение int к char, при котором отбрасываются значения старших битов. Это приводило к тому, что примерно в 1 случае из 256 удавалось подключиться с любым паролем, зная имя пользователя.

Например, статический анализатор PVS-Studio выдает следующее предупреждение: CWE-197 (V642): Numeric Truncation Error. Опять-таки, эту CWE ошибку можно было бы обезвредить и не дать ей превратиться в CVE ещё на этапе написания кода.

В продолжение этой темы предлагаю посмотреть статью "Как PVS-Studio может помочь в поиске уязвимостей?".

Заключение

0-day уязвимости – вещь, от которой нет гарантированной защиты. Но вероятность их появления можно значительно уменьшить. Для этого могут быть использованы такие специализированные SAST решения, как PVS-Studio. Если в вашем проекте обнаружатся ошибки, которые можно классифицировать как CWE, то стоит обратить на них внимание и исправить. Несмотря на то, что лишь небольшое количество CWE по итогу пополнит список CVE, устраняя CWE-ошибки, вы защищаете своё приложение от многих потенциальных угроз.

Дополнительные ссылки

  1. Скачать и попробовать PVS-Studio
  2. Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей
  3. Классификация предупреждений PVS-Studio согласно Common Weakness Enumeration (CWE)
  4. Классификация предупреждений PVS-Studio согласно SEI CERT Coding Standard

PVS-Studio Static Analyzer as a Tool for Protection against Zero-Day Vulnerabilities. Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Ekaterina Nikiforova.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»