Контрольный список безопасности драйвера
В этой статье содержится контрольный список безопасности драйверов для разработчиков драйверов, помогающих снизить риск компрометации драйверов. Безопасность драйверов является крайне важной и непосредственно влияет на надежность. Когда Windows обнаруживает, что происходит неправильный доступ к памяти, он завершит работу ОС и отобразит синий экран ошибки. В качестве партнера Windows вы должны работать над уменьшением значительного влияния неработающего драйвера на жизнь наших клиентов.
Дополнительные сведения о преимуществах предоставления безопасного и надежного драйвера см. в руководстве по безопасности драйверов.
Общие сведения о безопасности драйверов
Недостаток безопасности — это любой недостаток, который позволяет злоумышленнику вызвать сбой драйвера таким образом, что он позволяет злоумышленнику получить несанкционированный доступ, управлять системой или компрометировать данные, потенциально вызывая сбой системы или стать неиспользуемым. Кроме того, уязвимости в коде драйвера могут позволить злоумышленнику получить доступ к ядру, создав возможность компрометации всей ОС.
Когда большинство разработчиков работают над своим драйвером, их основное внимание уделяется обеспечению правильной работы драйвера, а не на том, будут ли злоумышленники пытаться использовать уязвимости в их коде. Однако после освобождения драйвера злоумышленники могут попытаться провести проверку и выявить недостатки безопасности. Разработчики должны рассмотреть эти проблемы на этапе проектирования и реализации, чтобы свести к минимуму вероятность таких уязвимостей. Цель заключается в устранении всех известных недостатков безопасности перед освобождением драйвера.
Для создания более безопасных драйверов требуется сотрудничество системного архитектора (сознательно думая о потенциальных угрозах для драйвера), разработчике, реализующем код (оборонительные кодирование распространенных операций, которые могут быть источником эксплойтов), и тестовой команде (упреждающей попытке найти слабость и уязвимости). Благодаря правильной координации всех этих действий безопасность водителя значительно улучшается.
Помимо предотвращения проблем, связанных с атакой драйвера, многие из описанных шагов, таких как более точное использование памяти ядра, повышают надежность драйвера. Это снижает затраты на поддержку и повышает удовлетворенность клиентов вашим продуктом. Выполнение задач в контрольном списке ниже поможет достичь всех этих целей.
контрольный список безопасности :Завершить задачу безопасности, описанную в каждом из этих разделов.
Убедитесь, что драйвер ядра является обязательным
Использовать платформы драйверов
Управление контролем доступа драйверов
Контроль доступа только к драйверам, предназначенным для программного обеспечения
Следуйте рекомендациям по безопасному кодированию драйверов
Реализуйте совместимый с HVCI код
Следуйте рекомендациям по лучшим практикам написания кода для конкретных технологий
Добавьте заметки SAL в код драйвера
Провести одноранговую проверку кода
Используйте CodeQL для проверки кода драйвера
Используйте средство проверки драйверов для проверки уязвимостей
Проверьте код в тестах программы совместимости оборудования
Проверьте готовность к отправке драйверов с помощью таких инструментов, как BinSkim и SignTool
Не подписывать тестовый код драйвера для производственного использования
Просмотр ресурсов безопасного написания кода
Просмотрите сводку ключевых выводов
Убедитесь, что требуется драйвер ядра
контрольный список безопасности #1:Убедитесь, что требуется драйвер ядра, и что более низкий подход к риску, например служба Windows или приложение, не является лучшим вариантом.
Драйверы ядра работают в ядре Windows, и любые проблемы при их выполнении в ядре могут подвергнуть риску всю операционную систему. Если доступен любой другой вариант, скорее всего, это будет меньше затрат и меньше риска, чем создание нового драйвера ядра.
Дополнительные сведения об использовании встроенных драйверов Windows см. в Необходимо ли написать драйвер?.
Сведения об использовании фоновых задач см. в разделе Поддержка приложения с помощью фоновых задач.
Сведения об использовании служб Windows см. в Службах Windows.
Использование фреймворков драйверов
контрольный список безопасности #2:использовать платформы драйверов для уменьшения размера кода и повышения надежности и безопасности.
Используйте Платформы драйверов Windows для уменьшения размера кода и повышения надежности и безопасности. Чтобы приступить к работе, просмотрите Использование WDF для разработки драйвера. Сведения об использовании платформы драйверов в режиме более низкого риска (UMDF) см. в разделе Выбор модели драйвера.
Написание устаревшего модели драйвера Windows (WDM) драйвером является более трудоемким, дорогостоящим и включает в себя воссоздание кода, доступного в платформах драйверов.
Исходный код Windows Driver Framework (WDF) является открытым исходным кодом и доступен на GitHub. Это тот же исходный код WDF, который поставляется в Windows. Вы можете эффективнее отлаживать драйвер, когда можно отслеживать взаимодействие между драйвером и WDF. Скачайте его из https://github.com/Microsoft/Windows-Driver-Frameworks.
DMF — платформа модуля драйвера
Рассмотрите возможность использования платформы модулей драйверов (DMF) в проекте драйвера. Разработанная командой Microsoft Surface, DMF — это платформа, которая позволяет создавать объекты WDF, называемые модулями DMF. Код для этих модулей DMF можно совместно использовать для разных драйверов. Кроме того, DMF предоставляет библиотеку модулей DMF, разработанных для драйверов и повторного использования кода для таких задач, как поток и управление ввода-выводами. Модуль DMF используется для инкапсуляции задач драйвера в меньшие единицы. Каждый модуль является автономным и имеет собственный код, контекст и обратные вызовы, что упрощает повторное использование. Дополнительные сведения см. в введение в фреймворк модулей драйверов и документации сайта GitHub.
Управление доступом к драйверу
Пункт 3 контрольного списка безопасности:Проверьте драйвер, чтобы убедиться, что вы правильно управляете доступом.
Управление доступом к драйверу — WDF
Драйверы должны работать, чтобы запретить пользователям неуместный доступ к устройствам и файлам компьютера. Чтобы предотвратить несанкционированный доступ к устройствам и файлам, необходимо:
При необходимости назовите объекты устройства. Именованные объекты устройств обычно требуются только для совместимости с устаревшими системами, например, если у вас есть приложение, которое ожидает открытия устройства под определённым именем, или если вы используете не-PNP устройство или контроллер. Обратите внимание, что драйверам WDF не нужно присваивать своим устройствам PnP имя FDO для создания символьной ссылки с помощью WdfDeviceCreateSymbolicLink.
Безопасный доступ к объектам и интерфейсам устройства.
Чтобы разрешить приложениям или другим драйверам WDF доступ к PDO устройства PnP, следует использовать интерфейсы устройств. Дополнительные сведения см. в разделе Использование интерфейсов устройств. Интерфейс устройства служит символьной ссылкой на PDO стека устройств.
Одним из лучших способов управления доступом к PDO является указание строки SDDL в INF. Если строка SDDL отсутствует в INF-файле, Windows будет применять дескриптор безопасности по умолчанию. Дополнительные сведения см. в разделе защита объектов устройств и SDDL для объектов устройств.
Дополнительные сведения об управлении доступом см. в следующих статьях:
управление доступом к устройству в драйверах KMDF
Имена, дескрипторы безопасности и классы устройств — обеспечение доступности объектов устройств... и безопасно январь-февраль 2017 года бюллетеня
Управление доступом к драйверу — WDM
Если вы работаете с драйвером WDM и использовали именованный объект устройства, вы можете использовать IoCreateDeviceSecure и указать SDDL для защиты. При реализации IoCreateDeviceSecure всегда указывайте GUID пользовательского класса для DeviceClassGuid. Здесь не следует указывать существующий GUID класса. Это может привести к разрыву параметров безопасности или совместимости для других устройств, принадлежащих к данному классу. Дополнительные сведения см. в разделе WdmlibIoCreateDeviceSecure.
Дополнительные сведения см. в следующих статьях:
управление доступом к устройствам
Контроль доступа к пространству имен устройств
модель безопасности Windows для разработчиков драйверов
Иерархия рисков идентификаторов безопасности (SID)
В следующем разделе описывается иерархия рисков распространенных идентификаторов SID, используемых в коде драйвера. Общие сведения о SDDL см. в разделе SDDL для объектов устройств, SID строки и синтаксис строки SDDL .
Важно понимать, что если вызывающие абоненты с низким уровнем привилегий могут получить доступ к ядру, риск кода увеличивается. На этой сводной схеме риск увеличивается, когда вы позволяете SID с более низкими привилегиями доступ к функциям вашего драйвера.
SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)
Следуя общему принципу безопасности наименьших привилегий, настройте только минимальный уровень доступа, необходимый для работы драйвера.
Контроль безопасности WDM Granular IOCTL
IOCTL (входной и выходной элемент управления) в Windows — это системный вызов для операций ввода и вывода для конкретного устройства. IoCTLs используются приложениями для взаимодействия с драйверами устройств, позволяя им отправлять команды или запрашивать сведения из оборудования. Дополнительные сведения см. в разделе Введение в коды управления ввода-вывода и пример запроса ввода-вывода — обзор.
Для дальнейшего управления безопасностью при отправке IOCTL вызовов в режиме пользователя код драйвера может включать функцию IoValidateDeviceIoControlAccess. Эта функция позволяет драйверу проверять права доступа. При получении IOCTL драйвер может вызвать IoValidateDeviceIoControlAccess, указывая FILE_READ_ACCESS, FILE_WRITE_ACCESS или оба.
Реализация детализированного элемента управления безопасностью IOCTL не заменяет необходимость управления доступом драйверов с помощью описанных выше методов.
Дополнительные сведения см. в определении кодов управления ввода-вывода и вопросах безопасности кодов управления ввода-вывода.
Управление доступом только к драйверам программного обеспечения
контрольный список безопасности #4:Если будет создан драйвер только для программного обеспечения, необходимо реализовать дополнительные средства контроля доступа.
Драйверы ядра, работающие только на программном обеспечении, не используют Plug-and-Play (PnP) для привязки к конкретным аппаратным идентификаторам и могут работать на любом компьютере. Такой драйвер можно использовать для целей, отличных от первоначально предполагаемого, создания вектора атаки.
Так как драйверы ядра только для программного обеспечения содержат дополнительный риск, они должны быть ограничены для выполнения на определенном оборудовании (например, с помощью уникального идентификатора PnP для включения создания драйвера PnP или проверки таблицы SMBIOS на наличие определенного оборудования).
Например, представьте, что OEM Fabrikam хочет распространить драйвер, который включает утилиту для разгона для своих систем. Если этот драйвер, работающий только программно, будет выполнен на системе от другого производителя оборудования, это может привести к нестабильности системы или её повреждению. Системы Fabrikam должны включать уникальный идентификатор PnP, чтобы включить создание драйвера PnP, который также обновляется с помощью Центра обновления Windows. Если это невозможно, и компания Fabrikam создает устаревший драйвер, этот драйвер должен использовать другой метод для проверки того, что он запускается в системе Fabrikam (например, путем изучения таблицы SMBIOS перед включением любых возможностей).
Следуйте рекомендациям по безопасному написанию кода драйвера
проверочный список по безопасности #5:Проверьте ваш код и устраните все известные уязвимости.
Основное действие создания безопасных драйверов — определение областей в коде, которые необходимо изменить, чтобы избежать известных уязвимостей программного обеспечения. Многие из этих известных уязвимостей программного обеспечения имеют дело с строгим отслеживанием использования памяти, чтобы избежать проблем с другими пользователями, перезаписывающими или иначе компрометируя расположения памяти, которые использует ваш драйвер.
Средства сканирования кода, такие как CodeQL и определенные тесты драйвера, можно использовать для поиска некоторых, но не всех этих уязвимостей. Эти средства и тесты описаны далее в этом разделе.
Буферы памяти
Всегда проверяйте размеры входных и выходных буферов, чтобы убедиться, что буферы могут содержать все запрошенные данные. Дополнительные сведения см. в разделе Сбой проверки размера буферов.
Правильно инициализировать все выходные буферы нулями, прежде чем вернуть их вызывающему объекту. Дополнительные сведения см. в разделе Сбой инициализации буферов вывода.
Проверьте буферы переменной длины. Дополнительные сведения см. в разделе Ошибка проверки буферов Variable-Length. Дополнительные сведения о работе с буферами и использовании ProbeForRead для проверки адреса буфера см. в обработки буферов.
Используйте подходящий метод для доступа к буферам данных с помощью ioCTLs
Одной из основных обязанностей драйвера Windows является передача данных между приложениями в пользовательском режиме и устройствами системы. Три метода доступа к буферам данных показаны в следующей таблице.
Тип буфера IOCTL | Сводка | Дополнительные сведения |
---|---|---|
METHOD_BUFFERED | Рекомендуется для большинства ситуаций | Использование буферизованного ввода-вывода |
METHOD_IN_DIRECT или METHOD_OUT_DIRECT | Используется в некоторых высокоскоростных операциях ввода-вывода оборудования. | Использование прямых операций ввода-вывода |
METHOD_NEITHER | Избегайте, если это возможно | Использование без буферизированного и непосредственного ввода-вывода |
Как правило, буферный ввод-вывод рекомендуется, так как он предоставляет наиболее безопасные методы буферизации. Но даже при использовании буферизованного ввода-вывода существуют риски, такие как внедренные указатели, которые должны быть устранены.
Дополнительные сведения о работе с буферами в ioCTLs см. в методах доступа к буферам данных.
Ошибки при использовании буферизованного ввода-вывода iOCTL
Проверьте размер буферов, связанных с IOCTL. Дополнительные сведения см. в разделе Сбой проверки размера буферов.
Правильно инициализировать выходные буферы. Дополнительные сведения см. в разделе Сбой инициализации буферов вывода.
Правильно проверьте буферы переменной длины. Дополнительные сведения см. в разделе Ошибка проверки буферов Variable-Length.
При использовании буферизованного ввода-вывода убедитесь, что возвращаете соответствующую длину для OutputBuffer в поле Информация структуры IO_STATUS_BLOCK. Не просто возвращайте длину непосредственно из запроса READ. Например, рассмотрим ситуацию, когда возвращенные данные из пользовательского пространства указывают на наличие буфера 4K. Если драйвер фактически должен вернуть только 200 байт, но вместо этого просто возвращает 4K в поле "Информация", произошла уязвимость раскрытия информации. Эта проблема возникает, так как в более ранних версиях Windows буфер, который используется диспетчером операций ввода-вывода для буферизованного ввода-вывода, не равен нулю. Таким образом, пользовательское приложение получает обратно исходные 200 байт данных плюс 4K-200 байт из буфера (содержимое нестраничного пула). Этот сценарий может происходить со всеми использованиями буферизованного ввода и вывода, а не только с IOCTLs.
Ошибки прямого ввода-вывода в IOCTL
Правильно обрабатывать буферы нулевой длины. Дополнительные сведения см. в ошибках прямого ввода-вывода .
Ошибки при обращении к адресам пространства пользователя
Проверьте указатели, внедренные в буферные запросы ввода-вывода. Дополнительные сведения см. в разделе "Ошибки в ссылках", User-Space "Адреса",.
Проверьте любой адрес в пространстве пользователя перед попыткой его использования, используя API, такие как ProbeForRead.
Код драйвера должен правильно использовать память
Все выделения пула драйверов должны находиться в неисполняемом (NX) пуле. Использование пулов памяти NX по сути является более безопасным, чем использование исполняемых пулов, нестраничных (NP), и обеспечивает лучшую защиту от атак переполнения.
Чтобы драйверы могли поддерживать виртуализацию HVCI, существуют дополнительные требования к памяти. Дополнительные сведения см. в разделе Реализация совместимого кода HVCI далее в этой статье.
Уязвимости TOCTOU
Существует потенциальная уязвимость времени проверки до времени использования (TOCTOU) при использовании прямого ввода-вывода (IOCTL или для чтения/записи). Помните, что при доступе драйвера к буферу данных пользователя приложение пользователя может одновременно получать доступ к тому же буферу данных.
Чтобы управлять этим риском, скопируйте все параметры, которые необходимо проверить из буфера данных пользователя в память, доступную исключительно из режима ядра (например, стека или пула). Как только пользовательское приложение не сможет получить доступ к данным, проверьте их, а затем работайте с переданными данными.
Считывание и запись в регистры, специфичные для модели MSR
Встроенные компоненты компилятора, такие как __readmsr и __writemsr, можно использовать для доступа к регистрам, зависящим от модели. Если этот доступ необходим, драйвер должен всегда проверять, что регистр для чтения или записи ограничен ожидаемым индексом или диапазоном.
Дополнительные сведения и примеры кода см. в статье Предоставление возможности чтения и записи MSR в Рекомендации по ограничению поведения с высоким уровнем привилегий в драйверах режима ядра.
Ручки
- Проверка дескрипторов, передаваемых между памятью в режиме пользователя и в режиме ядра. Дополнительные сведения см. в разделе Управление дескрипторами и Сбой проверки дескрипторов объектов.
Объекты устройства
Защита объектов устройств. Дополнительные сведения см. в разделе "Защита объектов устройств".
Проверка объектов устройства. Для получения дополнительной информации см. раздел Ошибка проверки правильности объектов устройств.
ПИРы (планы интегрированных ресурсов)
Пакеты запросов ввода-вывода Windows (IRPs) используются для обмена данными о запросах ввода-вывода между драйверами операционной системы и режима ядра, инкапсулируя все необходимые сведения в пакете. IRPs упрощают асинхронную передачу данных, синхронизацию и обработку ошибок, обеспечивая эффективное и надежное взаимодействие с аппаратными устройствами. Дополнительные сведения см. в пакетах запросов ввода-вывода и в обзоре модели ввода-вывода Windows.
WDF и IRP
Одним из преимуществ использования WDF является то, что драйверы WDF обычно не обращаются напрямую к IRPs. Например, каркас преобразует WDM IRP, которые представляют операции чтения, записи и управления вводом-выводом, в объекты запросов каркаса, которые KMDF/UMDF получают в очередях ввода-вывода. По возможности настоятельно рекомендуется использовать WDF.
Если вам нужно написать драйвер WDM, ознакомьтесь со следующими рекомендациями.
Правильное управление буферами ввода-вывода IRP
Ознакомьтесь со следующими разделами, посвященными проверке входных значений IRP:
DispatchReadWrite с помощью буферизованного ввода-вывода
ошибки в буферизованном вводе-выводе
Чтение и запись ждущей функции с использованием прямого ввода-вывода
ошибки в прямого ввода-вывода
Проверьте значения, связанные с IRP, например адреса буфера и длины.
Если вы решили использовать Neither I/O, имейте в виду, что в отличие от операций чтения и записи, а также в отличие от буферного ввода/вывода и прямого ввода/вывода, при использовании Neither I/O IOCTL указатели на буфер и длины не проверяются диспетчером ввода/вывода.
Правильно обрабатывать операции завершения IRP
Драйвер никогда не должен завершать IRP со значением состояния STATUS_SUCCESS
, если он действительно не поддерживает и не обрабатывает его. Сведения о правильных способах обработки операций завершения IRP см. раздел Завершение IRP.
Управление состоянием ожидания IRP драйвера
Драйвер должен пометить IRP как ожидающий до его сохранения и должен рассмотреть возможность включения вызова IoMarkIrpPending и назначения в заблокированной последовательности. Дополнительные сведения см. в разделе Сбой проверки состояния драйвера и Удержание входящих ИРП при приостановке устройства.
Правильно осуществлять обработку операций по отмене IRP
Операции отмены могут быть сложными для правильного кода, так как обычно они выполняются асинхронно. Проблемы в коде, который обрабатывает операции отмены, могут быть незамеченными в течение длительного времени, так как этот код обычно не выполняется часто в работающей системе. Не забудьте прочитать и понять все сведения, предоставленные в разделе "Отмена IRPs". Обратите особое внимание на синхронизацию отмены IRP и вопросы, которые следует учитывать при отменеIRP.
Один из рекомендуемых способов свести к минимуму проблемы синхронизации, связанные с операциями отмены, — реализовать очередь IRP, безопасную для отмены.
Правильно обрабатывать операции очистки и закрытия IRP
Убедитесь, что вы понимаете разницу между IRP_MJ_CLEANUP и IRP_MJ_CLOSE запросами. Запросы на очистку поступают после того, как приложение закрывает все дескрипторы объекта файла, но иногда до завершения всех запросов ввода-вывода. Запросы на закрытие поступают после завершения или отмены всех запросов ввода-вывода для объекта файла. Дополнительные сведения см. в следующих статьях:
Подпрограммы DispatchCreate, DispatchClose и DispatchCreateClose
Ошибки в обработке операций очистки и закрытия
Дополнительные сведения о правильной обработке IRPs см. в разделе Дополнительные ошибки при обработке IRPs.
Использование безопасных функций
Используйте безопасные строковые функции. Для получения дополнительной информации см. Использование безопасных строковых функций.
Используйте безопасные арифметические функции. Для получения дополнительной информации см. функции безопасной целочисленной библиотеки.
Используйте функции безопасного преобразования. Дополнительные сведения см. в сводке Kernel-Mode безопасных целых функций.
Другие проблемы безопасности
Используйте блокировку или переблокированную последовательность, чтобы предотвратить условия гонки. Дополнительные сведения см. в разделе Ошибки в многопроцессорной среде.
Убедитесь, что сетевые фильтры интерфейса транспортного драйвера (TDI) или поставщики уровня услуг (LSPs) не устанавливаются драйвером или связанными пакетами программного обеспечения во время установки или использования. Вместо этого используйте современные API, такие как платформа фильтрации Windows (МПП) .
Дополнительные уязвимости кода
Помимо возможных уязвимостей, описанных здесь, в этой статье содержатся дополнительные сведения о повышении безопасности кода драйвера в режиме ядра: создание надежных драйверов Kernel-Mode.
Дополнительные сведения о безопасном кодировании C и C++ см. в ресурсах безопасного написания кода в конце этой статьи.
Реализация совместимого кода HVCI
Контрольный список безопасности №6:убедитесь, что ваш драйвер использует память, совместимую с HVCI.
Целостность памяти и совместимость с HVCI
Целостность памяти, также известная как защищенное гипервизором целостность кода (HVCI), использует аппаратные технологии и виртуализацию для изоляции функции принятия решений о целостности кода (CI) от остальной части операционной системы. При использовании безопасности на основе виртуализации для изоляции CI единственный способ, как память ядра может стать исполняемой, — это через проверку CI. Это означает, что страницы памяти ядра никогда не могут быть одновременно записываемыми и исполняемыми (W+X), и исполняемый код не может быть напрямую изменён.
Чтобы реализовать совместимый код HVCI, убедитесь, что код драйвера выполняет следующие действия:
- По умолчанию выбирает NX
- Использует NX API-интерфейсы и флаги для выделения памяти (NonPagedPoolNx)
- Не использует разделы, которые являются записываемыми и исполняемыми
- Не пытается напрямую изменить исполняемую системную память
- Не использует динамический код в ядре
- Не загружает файлы данных как исполняемые
- Выравнивание секций кратно 0x1000 (PAGE_SIZE). Например, DRIVER_ALIGNMENT=0x1000
Дополнительные сведения об использовании средства и списке несовместимых вызовов памяти см. в разделе Реализация совместимого кода HVCI.
Дополнительные сведения о проверке безопасности связанных системных принципов см. в тесте целостности кода HyperVisor и Hypervisor-Protected целостности кода (HVCI).
Повышение безопасности установки устройств
элемент контрольного списка безопасности #7:просмотрите инструкции по созданию и установке драйвера, чтобы убедиться, что вы следуете наилучшим практикам.
При создании кода, устанавливающего пакет драйвера, необходимо убедиться, что установка устройства всегда будет выполняться безопасно. Установка безопасного устройства — это одна из следующих действий:
- Ограничивает доступ к устройству и его классам интерфейса устройства
- Ограничивает доступ к службам драйверов, созданным для устройства.
- Защита файлов драйверов от изменения или удаления
- Ограничивает доступ к записям реестра устройства
- Ограничивает доступ к классам WMI устройства
- Правильно использует функции SetupAPI
Дополнительные сведения см. в следующих статьях:
Создание безопасной установки устройств
Руководство по использованию SetupAPI
Использование функций установки устройств
дополнительные разделы по установке устройств и драйверов
Следуйте рекомендациям по использованию кода для конкретных технологий
контрольный список безопасности, пункт #8:Ознакомьтесь с указанным ниже специфическим для технологии руководством для вашего драйвера.
Файловые системы
Дополнительные сведения о безопасности драйвера файловой системы см. в следующих статьях:
Общие сведения о безопасности файловой системы
проблемы с безопасностью файловой системы
Функции безопасности для файловых систем
Сосуществование с другими драйверами фильтров файловой системы
Инициатива по вирусу Майкрософт
Инициатива Microsoft по борьбе с вирусами (MVI) помогает организациям совершенствовать решения безопасности, на которые полагаются наши клиенты для своей защиты. Корпорация Майкрософт предоставляет средства, ресурсы и знания для повышения производительности, надежности и совместимости. Корпорация Майкрософт сотрудничает с партнерами MVI, чтобы определить и следовать рекомендациям по безопасному развертыванию (SDP) для поддержки безопасности и устойчивости наших взаимных клиентов.
Если вы являетесь поставщиком антивирусной программы, обратитесь к microsoft Virus Initiative, чтобы узнать, как присоединиться к MVI для получения дополнительной помощи по развертыванию программного обеспечения. Сведения о том, как поставщики безопасности могут лучше использовать интегрированные возможности безопасности Windows для повышения безопасности и надежности, см. в рекомендациях по обеспечению безопасности Windows для интеграции средств безопасности и управления ими.
NDIS — сеть
Сведения о безопасности драйверов NDIS см. в разделе Проблемы безопасности для сетевых драйверов.
Принтеры
Сведения, связанные с безопасностью драйвера принтера, см. в статье Вопросы безопасности драйвера принтера версии 4.
Проблемы безопасности драйверов получения образов Windows (WIA)
Сведения о безопасности WIA см. в разделе Проблемы с безопасностью для драйверов приобретения образов Windows (WIA).
Добавление заметок SAL в код драйвера
список проверки безопасности #9:Добавить аннотации SAL в код вашего драйвера.
Язык заметки исходного кода (SAL) предоставляет набор заметок, которые можно использовать для описания того, как функция использует свои параметры, предположения о них и гарантии того, что она делает после завершения. Аннотации определяются в заголовочном файле sal.h
. Анализ кода Visual Studio для C++ использует аннотации SAL для изменения анализа функций. Дополнительные сведения о разработке драйверов Windows с использованием SAL 2.0 см. в аннотациях SAL 2.0 для драйверов Windows и об использовании аннотаций SAL для уменьшения дефектов кода C/C++.
Общие сведения о SAL см. в этой статье, доступной в OSR. заметки SAL: Не ненавидьте меня, потому что я красива
Проведение совместной проверки кода
контрольный список безопасности #10:проведите взаимопроверку кода, чтобы выявить проблемы, не обнаруженные другими средствами и процессами
Найдите опытных рецензентов кода, чтобы обнаружить проблемы, которые вы могли упустить. Чужой взгляд часто замечает проблемы, которые вы могли упустить из виду.
Если у вас нет подходящих сотрудников для внутреннего аудита кода, рассмотрите возможность привлечения внешних экспертов для этой цели.
Выполнение анализа угроз
контрольный список безопасности #11:изменить существующую модель угроз драйвера или создать пользовательскую модель угроз для драйвера.
При рассмотрении безопасности общая методология заключается в создании конкретных моделей угроз, которые пытаются описать типы атак, которые могут быть возможны. Этот метод полезен при разработке драйвера, так как он заставляет разработчика заранее рассмотреть потенциальные векторы атак против драйвера. После выявления потенциальных угроз разработчик драйвера может рассмотреть возможность защиты от этих угроз, чтобы повысить общую безопасность компонента драйвера.
В этой статье приводятся рекомендации по созданию упрощенной модели угроз: моделирование угроз для драйверов. В этой статье приведен пример схемы модели угроз драйвера, которая может использоваться в качестве отправной точки для драйвера.
Рекомендации по жизненному циклу разработки безопасности (SDL) и связанные средства можно использовать IHV и OEM для повышения безопасности своих продуктов. Дополнительные сведения см. в рекомендациях по SDL дляизготовителей оборудования.
Использование CodeQL для проверки кода драйвера
контрольный список безопасности #12:Используйте CodeQL для проверки уязвимостей в коде драйвера.
CodeQL, GitHub, является подсистемой анализа семантического кода, и сочетание обширного набора запросов безопасности вместе с надежной платформой делает его ценным инструментом для защиты кода драйвера. Дополнительные сведения см. в разделе CodeQL и в тесте логотипа статических инструментов.
Проверка уязвимостей с помощью средства проверки драйверов
элемент контрольного списка безопасности #13:Использовать средство проверки драйверов для проверки уязвимостей в коде драйвера.
Средство проверки драйверов использует набор правил интерфейса и модель операционной системы, чтобы определить, правильно ли работает драйвер с операционной системой Windows. Средство проверки драйверов находит дефекты в коде драйвера, которые могут указывать на потенциальные ошибки в драйверах.
Средство проверки драйверов позволяет выполнять динамическое тестирование драйвера. Средство проверки драйверов отслеживает драйверы в режиме ядра Windows и графические драйверы для обнаружения незаконных вызовов функций или действий, которые могут повредить систему. Подключенный отладчик позволяет просматривать выполнение кода ОС и драйвера в режиме реального времени. Средство проверки драйверов может подвергать драйверам Windows различные стрессы и тесты, чтобы найти неправильное поведение. Дополнительные сведения см. в Проверке драйверов.
Драйвер Verifier работает с драйверами WDM и KMDF. Сведения о том, что он может проверить, см. в следующих разделах.
Дополнительные сведения о драйверах, с которыми может работать средство проверки драйверов, см. в правилах соответствия DDI и поддерживаемых драйверах . Дополнительные правила проверки для конкретных типов драйверов см. в следующей статье:
- правила для драйверов NDIS
- Правила драйверов Storport
- правила для драйверов аудио
- Правила для драйверов AVStream
Чтобы ознакомиться с DV, можно использовать один из примеров драйверов (например, рекомендуемый пример тостера: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).
Проверка кода с помощью тестов программы совместимости оборудования
контрольный список безопасности #14:Использовать тесты программы совместимости оборудования, касающиеся безопасности, чтобы проверить наличие проблем с безопасностью.
Программа совместимости оборудования включает тесты, связанные с безопасностью, можно использовать для поиска уязвимостей кода. Программа совместимости оборудования Windows использует тесты в комплекте аппаратных лабораторий Windows (HLK). Тесты основы устройств HLK можно использовать в командной строке для выполнения кода драйвера и проверки на наличие слабых мест. Общие сведения об основных тестах устройства и программе совместимости оборудования см. в комплекте аппаратных лабораторий Windows.
Ниже приведены примеры тестов, которые могут быть полезны для проверки кода драйвера для некоторых действий, связанных с уязвимостями кода:
DF — нечеткий случайный тест IOCTL (надежность)
DF — нечеткие вложенные тесты (надежность)
DF — Фазз-тест FSCTL с нулевой длиной буфера (надежность)
DF — нечеткий случайный тест FSCTL (надежность)
DF — тест разнообразных API Fuzz (достоверность)
Кроме того, можно использовать фуззинг задержки синхронизации ядра, который включен в программу проверки драйверов.
Тесты CHAOS (одновременное выполнение аппаратных средств и операционных систем) выполняют одновременно различные тесты драйверов PnP, фаззинг тесты драйверов устройств и тесты системы питания. Дополнительные сведения см. в тестах CHAOS (основы устройств) .
Базовые тесты на проникновение устройств выполняют различные формы вторжения через ввод данных, которые являются критически важным компонентом тестирования безопасности. Тестирование атак и проникновений может помочь выявить уязвимости в программных интерфейсах. Дополнительные сведения см. в тестах на проникновение (фундаментальные принципы устройства).
Используйте Device Guard — тест соответствия требованиям, а также другие средства, описанные в этой статье, чтобы убедиться, что драйвер совместим с HVCI.
Настраиваемые и доменные инструменты тестирования
Рассмотрите возможность разработки тестов безопасности для конкретного домена. Чтобы разработать дополнительные тесты, соберите входные данные от оригинальных конструкторов программного обеспечения, а также несвязанные ресурсы разработки, знакомые с определенным типом драйвера, и один или несколько людей, знакомых с анализом вторжений и предотвращением вторжений в безопасность.
Проверка готовности к отправке драйверов с помощью таких инструментов, как BinSkim и SignTool
контрольный список безопасности #15:проверить скомпилированный код с помощью таких инструментов, как BinSkim и SignTool, прежде чем отправить его в центр партнеров.
Используйте такие средства, как BinSkim и SignTool, чтобы проверить двоичные файлы, чтобы проверить скомпилированный код перед отправкой в центр партнеров для распространения с помощью Центра обновления Windows. Наличие средств для проверки скомпилированных двоичных файлов, прежде чем они отправляются для распространения, добавляется в другой уровень защиты.
BinSkim
BinSkim может выявлять методики кодирования и сборки, которые потенциально могут сделать двоичный файл уязвимым. BinSkim проверяет наличие:
- Использование устаревших наборов средств компилятора. Двоичные файлы должны компилироваться в самых последних наборах средств компилятора, где это возможно, чтобы максимально повысить эффективность использования текущих средств компилятора и устранения рисков безопасности, предоставляемых ОС.
- Небезопасные параметры компиляции - Двоичные файлы должны быть скомпилированы с максимально безопасными параметрами, чтобы обеспечить включение механизмов обеспечения безопасности, предоставляемых ОС, максимально повысить выявление ошибок компилятора и отчетов об исправляемых предупреждениях, среди прочего.
- Проблемы с подписыванием. Подписанные двоичные файлы должны быть подписаны с помощью криптографически надежных алгоритмов.
BinSkim — это средство с открытым исходным кодом и создает выходные файлы, использующие формат обмена статическими результатами анализа (SARIF) . BinSkim заменяет прежнее средство BinScope.
Дополнительные сведения о BinSkim см. в разделе Использование BinSkim для проверки двоичных файлов и руководстве пользователя BinSkim.
SignTool
Используйте SignTool для проверки файлов драйверов с подписью выпуска. Дополнительные сведения см. в разделе Проверка подписи файла драйвера Release-Signed и Проверка подписи файла каталога, подписанного сертификатом коммерческого выпуска.
Не подписывайте тестовый код с использованием производственных сертификатов
контрольный список безопасности #16:не выполнять разработку, тестирование и производственный код драйвера ядра.
Код драйвера ядра, используемый для разработки, тестирования или производства, может включать опасные возможности, которые представляют угрозу безопасности. Этот опасный код никогда не должен быть подписан сертификатом, доверенным Windows. Правильный механизм выполнения опасного кода драйвера — отключить безопасную загрузку UEFI, включить BCD "TESTSIGNING" и подписать код разработки, тестирования и производства с помощью ненадежного сертификата (например, созданного makecert.exe).
Код, подписанный доверенным сертификатом издателей программного обеспечения (SPC) или подписью Windows Hardware Quality Labs (WHQL), не должен способствовать обходу технологий целостности и безопасности кода Windows. Прежде чем код будет подписан доверенной сигнатурой SPC или WHQL, сначала убедитесь, что он соответствует рекомендациям из Создание Надежных Драйверов Kernel-Mode. Кроме того, код не должен содержать опасных действий, описанных ниже.
Ниже приведены примеры опасного поведения.
- Предоставление возможности сопоставлять произвольную память ядра, физическую память или память устройства с пользовательским режимом.
- Предоставление возможности чтения или записи произвольной памяти ядра, физической памяти или памяти устройства, включая ввод/вывод портов.
- Предоставление доступа к хранилищу, которое обходит контроль доступа Windows.
- Предоставление возможности изменять оборудование или встроенное ПО, которое драйвер не предназначен для управления.
Выполните подписывание выпускаемого драйвера и распространение вашего пакета драйверов через Центр обновления Windows.
Контрольный список безопасности #17:используйте Портал партнеров Windows для отправки пакета драйвера, который будет подписан и распределён через Центр обновления Windows.
Перед выпуском пакета драйвера для общественности вы отправляете пакет для сертификации. Дополнительные сведения см. в разделах "Тестирование производительности и совместимости" и "Начало работы с программой для оборудования".
Для распространения пакетов драйверов настоятельно рекомендуется использовать Центр обновления Windows. Центр обновления Windows предоставляет надежную, безопасную, глобальную масштабируемую и соответствующую нормативным требованиям систему распространения, которая должна использоваться для доставки обновлений драйверов. Дополнительные сведения см. в распространении пакета драйвера.
Используйте постепенный выпуск и пилотируемых в Центре партнеров для Windows Hardware для распространения пакета драйвера в определенных кругах предварительной оценки Windows, обеспечивая автоматический мониторинг и оценку. Отслеживайте развертывание драйвера с помощью мер драйвера Microsoft , таких как процент компьютеров без аварий в режиме ядра , для поддержания качества.
Описание методов безопасного развертывания программного обеспечения см. в разделе CISA безопасное развертывание программного обеспечения: как производители программного обеспечения могут обеспечить надежность для клиентов.
Узнайте, как сообщают о драйверах с помощью Центра отчетности Microsoft об уязвимых и вредоносных драйверах
элемент контрольного списка безопасности #18: Понять, как сообщается о драйверах с помощью Центра отчетов о уязвимостях и вредоносных драйверах Майкрософт
Любой пользователь может отправить сомнительный драйвер, используя Центр сообщений о уязвимых и вредоносных драйверах Microsoft. Дополнительные сведения о том, как драйверы отправляются для анализа, см. в этой записи блога. Улучшение безопасности ядра с помощью нового Центра отчетов о уязвимом и вредоносном драйвере Майкрософт
Центр отчетов может сканировать и анализировать драйверы Windows, созданные для архитектур x86 и x64. Уязвимые и вредоносные отсканированные драйверы помечаются для анализа и расследования группой уязвимых драйверов Майкрософт. После подтверждения уязвимых драйверов происходит соответствующее уведомление, и они добавляются в список блокировки уязвимых драйверов. Дополнительные сведения об этом см. в рекомендуемых Майкрософт правилах блокировки драйверов. Эти правила применяются по умолчанию к устройствам с поддержкой функции целостности кода, защищённых гипервизором (HVCI), и Windows 10 в режиме S.
Проверка защищенных ресурсов программирования
элемент контрольного списка безопасности #19:Просмотрите эти ресурсы, чтобы расширить понимание рекомендаций по безопасному кодированию, применимых к разработчикам драйверов.
База данных известных уязвимостей программного обеспечения NIST
Национальная база данных уязвимостей (NVD) — это доступный для поиска репозиторий ошибок программного обеспечения, связанных с безопасностью, включая драйверы Windows.
Поиск по базе данных уязвимостей NIST
Обзор базы данных национальной базы данных уязвимостей
Безопасные стандарты программирования
Carnegie Mellon University SEI CERT - Стандарт кодирования на C: правила разработки безопасных, надежных и защищенных систем (PDF).
MITRE — слабые места, устраненные стандартом безопасного кода CERT C
Безопасные организации программирования
SAFECode — https://safecode.org/
Университет Карнеги-Меллона SEI CERT
ОСР
OSR предоставляет обучение по разработке драйверов и консультационные услуги. Эти статьи из бюллетеня OSR обращают внимание на вопросы безопасности драйверов.
вы должны использовать защиту -- в системе драйвера & безопасность устройств
блокировка драйверов — опрос методов
Meltdown и Spectre: А как насчёт драйверов?
Исследование случая уязвимости драйвера
Безопасность цепочки поставок программного обеспечения и перечень программных компонентов (SBOMs)
инициатива "Целостность цепочки поставок", "Прозрачность и доверие" (SCITT)
Создание программной спецификации материалов (SBOM) с использованием SPDX в Microsoft
Книги
24 смертельных грехов программной безопасности: ошибки программирования и как их исправить Майкл Говард, Дэвид ЛеБлан и Джон Вьега
написание защищенного программного обеспечения второй выпуск, Майкл Ховард и Дэвид ЛеБланк
искусство оценки безопасности программного обеспечения: выявление и предотвращение уязвимостей программного обеспечения, Марк Доуд, Джон Макдональд и Джастин Шух
Безопасное кодирование в C и C++ (Серия SEI по программной инженерии) 2-е издание, Роберт C. Сикорд
Программирование модели драйвера Microsoft Windows (2-е издание), Уолтер Они
разработки драйверов с помощьюWindows Driver Foundation (справочник разработчика), Пенни Орвик и Гай Смит
Тренировка
Курсы по обучению драйверов Windows доступны у таких поставщиков, как:
Обучение безопасному программированию онлайн доступно из множества источников. Например, этот курс доступен из coursera на:
Выявление уязвимостей безопасности в программировании наC/C++.
SAFECode предлагает бесплатный учебный курс, а также:
Профессиональная сертификация
CERT предлагает профессиональный сертификат по безопасному кодированию.
Сводка по ключевым выводам
Безопасность драйверов является сложной задачей, содержащей множество элементов, но вот несколько ключевых моментов, которые следует рассмотреть:
Драйверы живут в ядре Windows и при возникновении проблем при выполнении в ядре подвергается риску вся операционная система. Поэтому внимательно относитесь к безопасности драйверов и учитывайте безопасность в процессе проектирования.
Примените принцип наименьших привилегий:
a. Использование строгой строки SDDL для ограничения доступа к драйверу
b. Дальнейшее ограничение отдельных IOCTL
Создайте модель угроз для идентификации векторов атак и рассмотрите возможность дальнейшего ограничения.
Будьте осторожными с встроенными указателями, которые передаются из пользовательского режима. Их необходимо проверить и обратиться к ним в блоке try-except, поскольку они подвержены проблемам типа «время проверки — время использования» (ToCToU), если только значение буфера не зафиксировано и не сравнивается.
Если вы не уверены, используйте METHOD_BUFFERED в качестве метода буферизации IOCTL.
Используйте служебные программы сканирования кода, такие как CodeQL, чтобы искать известные уязвимости кода и устранять все выявленные проблемы.
Найдите опытных рецензентов кода, чтобы обнаружить проблемы, которые вы могли упустить.
Используйте верификаторы драйверов и протестируйте драйвер с несколькими входными данными, включая пограничные случаи.