Предотвращение переполнения буфера

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

Warning

Никогда не используйте несвязанные строковые функции (strcpy, strcat, ,sprintfgets) в коде с учетом безопасности. Замените их ограниченными эквивалентами (StringCbCopy, StringCbCat, StringCbPrintf) из безопасной строковой библиотеки или используйте варианты суффикса C11 _s (strcpy_s, strcat_s).

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

переполнение статического буфера

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

переполнение кучи

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

ошибки индексирования массива

Ошибки индексирования массивов также являются источником переполнения памяти. Тщательная проверка границ и управление индексами поможет предотвратить переполнение памяти этого типа.

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

  • Maguire, Стив [1993], Написание надежного кода, ISBN 1-55615-551-4, Microsoft Press, Редмонд, Вашингтон.
  • Говард, Майкл и ЛеБлан, Дэвид [2003], Написание Безопасного Кода, 2-е изд., ISBN 0-7356-1722-8, Microsoft Press, Рэдмонд, Вашингтон, США.

Заметка

Эти ресурсы могут быть недоступны на некоторых языках и странах.

 

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

Меры защиты компилятора и компоновщика

Современные версии компилятора Microsoft C/C++ и компоновщика обеспечивают несколько уровней защиты от переполнения буфера. Всегда включите эти защиты в рабочих сборках:

Flag Purpose
/GS Обнаружение переполнения буфера стека (включено по умолчанию). Вставляет файлы cookie безопасности перед обратными адресами.
/sdl Включает дополнительные проверки безопасности, включая более строгий режим /GS инициализации переменных.
/DYNAMICBASE Рандомизация адресного пространства (ASLR). Случайным образом задает адреса нагрузки, чтобы сделать эксплуатацию сложнее.
/NXCOMPAT Предотвращение выполнения данных (DEP). Помечает страницы памяти как не исполняемые.
/CETCOMPAT Технология Intel Control-flow Enforcement (CET) для аппаратно защищённых теневых стеков.
/guard:cf Control Flow Guard (CFG). Проверяет целевые объекты непрямого вызова во время выполнения.

Important

Компилируйте весь новый код как минимум с /sdl и /GS. Для критически важных с точки зрения безопасности приложений также включите /guard:cf и компонуйте с /CETCOMPAT при работе с оборудованием, поддерживающим CET.

Средства анализа среды выполнения

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

  • AddressSanitizer (ASan): Компилируйте с /fsanitize=address, чтобы обнаруживать переполнения буфера, обращения к памяти после её освобождения и другие ошибки работы с памятью во время выполнения. Доступно в Visual Studio 2019 16.9 и более поздних версий.
  • Проверка приложений: Обнаруживает повреждения кучи, неправильное использование дескрипторов и другие распространённые ошибки программирования.
  • Статический анализ (/analyze): встроенный статический анализатор обнаруживает переполнение буфера, неинициализированные переменные и другие проблемы во время компиляции.