Модель безопасности Windows для разработчиков драйверов

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

В этом разделе описано, как модель безопасности Windows применяется к драйверам режима ядра.

Модель безопасности Windows

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

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

Модель безопасности включает в себя следующие понятия:

  • Идентификаторы безопасности (идентификаторы безопасности)
  • Маркеры доступа
  • Дескрипторы безопасности
  • Списки управления доступом (ACL)
  • Привилегии

Идентификаторы безопасности (идентификаторы безопасности)

Идентификатор безопасности (SID, также называемый субъектом) идентифицирует пользователя, группу или сеанс входа. У каждого пользователя есть уникальный идентификатор безопасности, который извлекается операционной системой при входе в систему.

Идентификаторы безопасности выдаются центром сертификации, например операционной системой или сервером домена. Некоторые идентификаторы безопасности хорошо известны и имеют имена и идентификаторы. Например, идентификатор безопасности S-1-1-0 идентифицирует всех (или мир).

Маркеры доступа

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

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

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

Дескрипторы безопасности

Каждый именованный объект Windows имеет дескриптор безопасности; некоторые неименованные объекты тоже. Дескриптор безопасности описывает идентификаторы безопасности владельца и группы для объекта, а также его списки управления доступом.

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

Дополнительные сведения о дескрипторах безопасности см. в документации по драйверу ядра.

Списки управления доступом

контроль доступа Списки (ACL) обеспечивают детальное управление доступом к объектам. ACL является частью дескриптора безопасности для каждого объекта.

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

Списки управления доступом для объектов устройств

ACL для объекта устройства можно задать любым из трех способов:

  • Задайте в дескрипторе безопасности по умолчанию для своего типа устройства.
  • Создается программным способом с помощью функции RtlCreateSecurityDescriptor и задается функцией RtlSetDaclSecurityDescriptor .
  • Указывается в SDDL в INF-файле устройства или в вызове процедуры IoCreateDeviceSecure .

Все драйверы должны использовать SDDL в INF-файле, чтобы указать списки управления доступом для своих объектов устройств.

SDDL — это расширяемый язык описания, который позволяет компонентам создавать списки управления доступом в строковом формате. SDDL используется как кодом в пользовательском режиме, так и в режиме ядра. На следующем рисунке показан формат строк SDDL для объектов устройства.

Схема, показывающая формат строк SDDL для объектов устройства.

Значение Access указывает тип разрешенного доступа. Значение SID указывает идентификатор безопасности, который определяет, к кому применяется значение Access (например, к пользователю или группе).

Например, следующая строка SDDL разрешает системным (SY) доступ ко всему и всем остальным (WD) только доступ на чтение:

“D:P(A;;GA;;;SY)(A;;GR;;;WD)”

Файл заголовка wdmsec.h также содержит набор предопределенных строк SDDL, которые подходят для объектов устройств. Например, файл заголовка определяет SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX следующим образом:

"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GRGWGX;;;RC)"

Первый сегмент этой строки позволяет ядру и операционной системе (SY) полностью контролировать устройство. Во втором сегменте любой пользователь из встроенной группы администраторов (BA) может получить доступ ко всему устройству, но не изменять список управления доступом. Третий сегмент позволяет всем пользователям (WD) считывать или записывать данные на устройство, а четвертый предоставляет те же права на ненадежный код (RC). Драйверы могут использовать предопределенные строки как есть или в качестве моделей для строк, зависящих от объекта устройства.

Все объекты устройств в стеке должны иметь одинаковые списки управления доступом. Изменение списков управления доступом на одном объекте устройства в стеке изменяет списки управления доступом во всем стеке устройств.

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

Подпрограмма IoCreateDeviceSecure поддерживает подмножество строк SDDL, использующих предопределенные идентификаторы безопасности, такие как WD и SY. API пользовательского режима и INF-файлы поддерживают полный синтаксис SDDL.

Проверки безопасности с помощью списков управления доступом

Когда процесс запрашивает доступ к объекту, проверки безопасности сравнивают списки управления доступом для объекта с идентификаторами безопасности в маркере доступа вызывающего объекта.

Система сравнивает ACE в строгом порядке сверху вниз и останавливается на первом соответствующем совпадении. Таким образом, при создании списка ACL всегда следует помещать ACE отказов выше соответствующих ACE предоставления. В следующих примерах показано, как выполняется сравнение.

Пример 1. Сравнение ACL с маркером доступа

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

Пример ACL файла

Разрешение SID Access
Allow Учет Запись, удаление
Allow Sales Добавление
Запрет Legal Добавление, запись, удаление
Allow Все Read

Этот ACL имеет четыре ACL, которые применяются специально к группам "Бухгалтерия", "Продажи", "Юридические" и "Все".

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

Пользователь Джим (S-1-5-21...)

Групповой учет (S-1-5-22...)

Группа юридических (S-1-5-23...)

Группировать всех (S-1-1-0)

При сравнении ACL файла с маркером доступа система сначала ищет ACE для пользователя Jim в ACL файла. Отсутствует, поэтому затем выполняется поиск ACE для группы "Бухгалтерия". Как показано в предыдущей таблице, ACE для группы учета отображается в качестве первой записи в списке управления доступом файла, поэтому процессу Джима предоставляется право на запись или удаление файла, и сравнение останавливается. Если ACE для юридической группы вместо этого предшествует ACE для учетной группы в ACL, процессу будет отказано в доступе на запись, добавление и удаление файла.

Пример 2. Сравнение ACL с ограниченным маркером

Система сравнивает ACL с ограниченным маркером так же, как и маркеры в маркере без ограничений. Однако идентификатор безопасности отказа в ограниченном маркере может соответствовать только запрету ACE в ACL.

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

Пользователь Джим (S-1-5-21...) Отрицать

Групповой учет (S-1-5-22...) Отрицать

Группа юридических (S-1-5-23...) Отрицать

Группировать всех (S-1-1-0)

В списке ACL файла не указан идентификатор безопасности Джима, поэтому система переходит к идентификатору БЕЗОПАСНОСТИ группы учета. Хотя ACL файла имеет ACE для группы учета, этот ACE разрешает доступ; Таким образом, он не соответствует идентификатору безопасности в ограниченном маркере процесса, который запрещает доступ. В результате система переходит к идентификатору БЕЗОПАСНОСТИ юридической группы. ACL для файла содержит ACE для юридической группы, которая запрещает доступ, поэтому процесс не может записывать, добавлять или удалять файл.

Привилегии

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

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

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

Сценарий модели безопасности Windows: создание файла

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

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

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

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

  1. Приложение пользовательского режима вызывает функцию CreateFile , передавая допустимое имя файла Microsoft Win32.
  2. Kernel32.dll пользовательского режима передает запрос в Ntdll.dll, который преобразует имя Win32 в имя файла microsoft Windows NT.
  3. Ntdll.dll вызывает функцию NtCreateFile с именем файла Windows. В Ntoskrnl.exe диспетчер ввода-вывода обрабатывает NtCreateFile.
  4. Диспетчер ввода-вывода перепаковывает запрос в вызов диспетчера объектов.
  5. Диспетчер объектов разрешает символьные ссылки и гарантирует, что у пользователя есть права на обход пути, по которому будет создан файл. Дополнительные сведения см. в разделе Проверки безопасности в диспетчере объектов.
  6. Диспетчер объектов вызывает системный компонент, которому принадлежит базовый тип объекта, связанный с запросом. Для запроса на создание файла этот компонент является диспетчером ввода-вывода, который владеет объектами устройства.
  7. Диспетчер ввода-вывода проверяет дескриптор безопасности для объекта устройства на соответствие маркеру доступа для процесса пользователя, чтобы убедиться, что у пользователя есть необходимый доступ к устройству. Дополнительные сведения см. в разделе Проверки безопасности в диспетчере ввода-вывода.
  8. Если у пользовательского процесса есть необходимый доступ, диспетчер ввода-вывода создает дескриптор и отправляет IRP_MJ_CREATE запрос драйверу для устройства или файловой системы.
  9. При необходимости драйвер выполняет дополнительные проверки безопасности. Например, если запрос указывает объект в пространстве имен устройства, драйвер должен убедиться, что вызывающий объект имеет необходимые права доступа. Дополнительные сведения см. в разделе Проверки безопасности в драйвере.

Проверки безопасности в диспетчере объектов

Ответственность за проверку прав доступа принадлежит компоненту самого высокого уровня, который может выполнять такие проверки. Если диспетчер объектов может проверить права доступа вызывающего объекта, он делает это. В противном случае диспетчер объектов передает запрос компоненту, ответственному за базовый тип объекта. Этот компонент, в свою очередь, проверяет доступ, если это возможно; Если это не удается, он передает запрос компоненту с более низким уровнем, например драйверу.

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

Проверки безопасности в диспетчере ввода-вывода

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

Если дескриптор дублируется, права можно удалить из копии, но не добавить в нее.

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

Режим доступа Win32 Права, относящиеся к объектам
GENERIC_READ ReadData
GENERIC_WRITE WriteData
GENERIC_EXECUTE Атрибуты ReadAttributes
GENERIC_ALL Все

Чтобы создать файл, процесс должен иметь права обхода по родительским каталогам в целевом пути. Например, чтобы создать \Device\CDROM0\Directory\File.txt, процесс должен иметь право на обход \Device, \Device\CDROM0 и \Device\CDROM0\Directory. Диспетчер ввода-вывода проверяет только права обхода для этих каталогов.

При анализе имени файла диспетчер операций ввода-вывода проверяет права обхода. Если имя файла является символьной ссылкой, диспетчер ввода-вывода разрешает его по полному пути, а затем проверяет права обхода, начиная с корневого каталога. Например, предположим, что символьная ссылка \DosDevices\D сопоставляется с именем устройства Windows NT \Device\CDROM0. Процесс должен иметь права на обход каталога \Device.

Дополнительные сведения см. в разделе Object Handles and Object Security.

Проверки безопасности в драйвере

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

При использовании драйверов WDM диспетчер операций ввода-вывода не выполняет проверки безопасности пространства имен, если объект устройства не был создан с указанием FILE_DEVICE_SECURE_OPEN. Если FILE_DEVICE_SECURE_OPEN не задан, драйвер отвечает за обеспечение безопасности своего пространства имен. Дополнительные сведения см. в разделах Управление доступом к пространству имен устройств и Защита объектов устройств.

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

Границы безопасности Windows

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

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

Частью процесса создания модели угроз является изучение границ безопасности и поиск непредвиденных путей. Дополнительные сведения см. в статье Моделирование угроз для драйверов.

Все данные, которые пересекают границу доверия, не являются доверенными и должны быть проверены.

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

Схема: область атаки драйвера с тремя драйверами ядра, приложением в контейнере приложения и приложением с правами администратора.

Так как контейнер приложения может предоставлять дополнительные ограничения и не выполняется на уровне администратора, путь (1) представляет собой более высокий путь риска для атаки эскалации, так как граница доверия находится между контейнером приложения (процесс с очень низким уровнем привилегий) и драйвером ядра.

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

Путь (3) — это пример пути выполнения кода, который пересекает несколько границ доверия, которые могут быть пропущены, если не создать модель угроз. В этом примере между драйвером 1 и драйвером 3 существует граница доверия, так как драйвер 1 принимает входные данные из приложения пользовательского режима и передает их непосредственно драйверу 3.

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

Рекомендации по модели Безопасность Windows

  • Задайте строгие списки управления доступом по умолчанию в вызовах подпрограммы IoCreateDeviceSecure .
  • Укажите списки управления доступом в INF-файле для каждого устройства. При необходимости эти списки управления доступом могут ослабить жесткие списки управления доступом по умолчанию.
  • Задайте FILE_DEVICE_SECURE_OPEN характеристику, чтобы применить параметры безопасности объекта устройства к пространству имен устройства.
  • Не определяйте списки IOCTL, разрешающие FILE_ANY_ACCESS, если такой доступ не может быть использован злоумышленником.
  • Используйте процедуру IoValidateDeviceIoControlAccess , чтобы усилить безопасность существующих IOCTLS, которые позволяют FILE_ANY_ACCESS.
  • Создайте модель угроз, чтобы изучить границы безопасности и найти непредвиденные пути. Дополнительные сведения см. в статье Моделирование угроз для драйверов.
  • Дополнительные рекомендации по обеспечению безопасности драйверов см. в разделе Контрольный список безопасности драйверов.

См. также:

Защита объектов устройств

Контрольный список безопасности драйверов