安全模型Read.docx
- 文档编号:26433774
- 上传时间:2023-06-19
- 格式:DOCX
- 页数:18
- 大小:26.50KB
安全模型Read.docx
《安全模型Read.docx》由会员分享,可在线阅读,更多相关《安全模型Read.docx(18页珍藏版)》请在冰豆网上搜索。
安全模型Read
Windows安全模型:
每个驱动程序作者都需要了解的内容
Updated:
July7,2004
OnThisPage
简介
Windows安全模型
安全场景:
创建一个文件
驱动程序安全责任
行动指南和资源
本文提供关于为MicrosoftWindows家族操作系统编写安全的内核模式驱动程序的信息。
其中描述了如何将Windows安全模型应用于驱动程序,并解释驱动程序作者必须采取哪些措施来确保其设备的安全性。
简介
Windows安全模型基于安全对象。
操作系统的每个组件都必须确保其负责的对象的安全性。
因此,驱动程序必须保证其设备和设备对象的安全性。
本文总结了如何将Windows安全模型应用于内核模式驱动程序,以及驱动程序编写人员必须采取哪些措施来确保其设备的安全性。
一些类型的设备适用于附加的设备特定要求。
请参阅MicrosoftWindowsDriverDevelopmentKit(DDK)中的设备特定的文档,以了解详细信息。
注意:
关于本文中讨论的例程和问题的当前文档,请参见WindowsDDK最新版本。
关于如何获取当前的DDK的信息,请参见
Topofpage
Windows安全模型
Windows安全模型主要基于每个对象的权限,以及少量的系统级特权。
安全对象包括(但不限于)进程、线程、事件和其它同步对象,以及文件、目录和设备。
对于每种类型的对象,一般的读、写和执行权限都映射到详细的对象特定权限中。
例如,对于文件和目录,可能的权限包括读或写文件或目录的权限、读或写扩展的文件属性的权限、遍历目录的权限,以及写对象的安全描述符的权限。
更多信息(包括完整的权限列表)请参见MSDN库的“安全性”节中的“安全性(常规)”,该库位于.
安全模型涉及以下概念:
•
安全标识符(SID)
•
存取令牌
•
安全描述符
•
访问控制列表(ACL)
•
特权
安全标识符(SID)
安全标识符(SID,也称为安全主体)标识一个用户、组或登录会话。
每个用户都有一个唯一的SID,在登录时由操作系统检索。
SID由一个权威机构(如操作系统或域服务器)分发。
一些SID是众所周知的,并且具有名称和标识符。
例如,SIDS-1-1-0标识所有人(或全世界)。
存取令牌
每个进程都有一个存取令牌。
存取令牌描述进程的完整的安全上下文。
它包含用户的SID、用户所属组的SID、登录会话的SID,以及授予用户的系统级特权列表。
默认情况下,当进程的线程与安全对象交互时,系统使用进程的主存取令牌。
但是,一个线程可以模拟一个客户端帐户。
当一个线程模拟客户端帐户时,它除了拥有自己的主令牌之外还有一个模拟令牌。
模拟令牌描述线程正在模拟的用户帐户的安全上下文。
模拟在远程过程调用(RemoteProcedureCall,RPC)处理中尤其常见。
描述线程或进程的受限制的安全上下文的存取令牌被称为受限令牌。
受限令牌中的SID只能设置为拒绝访问安全对象,而不能设置为允许访问安全对象。
此外,令牌可以描述一组有限的系统级特权。
用户的SID和标识保持不变,但是在进程使用受限令牌时,用户的访问权限是有限的。
CreateRestrictedToken函数创建一个受限令牌。
受限令牌对于运行不可信代码(例如电子邮件附件)很有用。
当您右键单击可执行文件,选择“运行方式”并选择“保护我的计算机和数据不受未授权程序的活动影响”时,MicrosoftWindowsXP就会使用受限令牌。
安全描述符
每个命名的Windows对象都有一个安全描述符,一些未命名的对象也有。
安全描述符描述对象的所有者和组SID,以及对象的ACL。
对象的安全描述符通常由创建该对象的函数创建。
当驱动程序调用IoCreateDevice或IoCreateDeviceSecure例程来创建设备对象时,系统将一个安全描述符应用于创建的设备对象并为对象设置ACL。
对于大多数设备,ACL是在设备信息(INF)文件中指定的。
访问控制列表
访问控制列表(ACL)允许细粒度地控制对对象的访问。
ACL是每个对象的安全描述符的一部分。
每个ACL包含零个或多个访问控制条目(ACE)。
而每个ACE仅包含一个SID,用来标识用户、组或计算机以及该SID拒绝或允许的权限列表。
设备对象的ACL
可以使用三种方式设置设备对象的ACL:
•
在其设备类型的默认安全描述符中设置。
•
由RtlCreateSecurityDescriptor函数通过编程方式创建,并由RtlSetDaclSecurityDescriptor函数进行设置。
•
在设备INF文件中使用安全描述符定义语言(SecurityDescriptorDefinitionLanguage,SDDL)指定,或者在对IoCreateDeviceSecure例程的调用中指定。
所有新的驱动程序都应该在INF文件中使用SDDL为其设备对象指定ACL。
SDDL是一种可扩展的描述语言,允许组件以字符串格式创建ACL。
用户模式和内核模式代码都使用SDDL。
图1显示了设备对象的SDDL字符串的格式。
图1.设备对象的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)中的任何人访问整个设备,但是不能更改ACL。
第三节允许所有人(WD)读或写设备,第四节将相同的权限授予不可信代码(RC)。
驱动程序可以按原样使用预定义字符串或者将其用作设备对象特定的字符串模型。
堆栈中的所有设备对象都应该具有相同的ACL。
更改堆栈中一个设备对象的ACL会更改整个设备堆栈的ACL。
然而,将新设备对象添加到堆栈中不会更改任何ACL,无论是新设备对象的ACL(如果它有ACL)还是堆栈中任何现有设备对象的ACL。
当驱动程序创建一个新的设备对象并将其附加到堆栈顶部时,驱动程序应该将堆栈的ACL复制到新设备对象,方法是从该设备对象的下一层驱动程序中复制DeviceObject.Characteristics字段。
IoCreateDeviceSecure例程支持SDDL字符串的一个子集,它使用预定义的SID(例如WD和SY)。
用户模式API和INF文件支持所有SDDL语法。
使用ACL进行安全检查
当进程请求访问一个对象时,安全检查将对象的ACL与调用方存取令牌中的SID进行比较。
系统按照严格的从上往下的顺序比较ACE,并在第一个相关的匹配处停止。
因此,在创建ACL时,应该始终将拒绝ACE放在相应且允许的ACE上方。
下面的例子展示了比较的方法。
例子1:
将ACL与存取令牌比较
例子1显示系统如何将ACL与调用方进程的存取令牌进行比较。
假设调用方想要打开具有表1所示ACL的文件。
表1.示例文件ACL
权限
SID
访问权
允许
Accounting
写、删除
允许
Sales
追加
拒绝
Legal
追加、写、删除
允许
Everyone
读
此ACL有4个ACE,分别应用于Accounting、Sales、Legal和Everyone组。
下一步,假设请求进程的存取令牌包含一个用户和三个组的SID,顺序如下:
用户Jim(S-1-5-21...)
组Accounting(S-1-5-22...)
组Legal(S-1-5-23...)
组Everyone(S-1-1-0)
在比较文件ACL与存取令牌时,系统首先在文件的ACL中查找用户Jim的ACE。
没有找到,所以接下去它查找Accounting组的ACE。
如表1所示,Accounting组的ACE就是文件的ACL中的第一个条目,因此Jim的进程被授予写或删除文件的权限,然后比较过程停止。
相反,如果ACL中Legal组的ACE在Accounting组的ACE前面,那么进程将无法获得对文件的写、追加和删除权限。
例子2:
将ACL与受限令牌比较
系统将ACL与受限令牌比较的方式与将其与不受限令牌比较的方式相同。
但是,受限令牌中的拒绝SID只能匹配ACL中的拒绝ACE。
例子2显示系统如何将文件的ACL与受限令牌进行比较。
假设文件具有与表1中所示的相同的ACL。
但是,在这个例子中,进程具有包含下列SID的受限令牌:
用户Jim(S-1-5-21...)拒绝
组Accounting(S-1-5-22...)拒绝
组Legal(S-1-5-23...)拒绝
组Everyone(S-1-1-0)
文件的ACL没有列出Jim的SID,所以系统继续比较Accounting组SID。
尽管文件的ACL中存在Accounting组的ACE,并且这条ACE允许访问,但是它与进程的受限令牌中的SID(它拒绝访问)不匹配。
因此,系统继续比较Legal组SID。
文件的ACL包含Legal组的一条ACE(拒绝访问),因此进程不能写、追加或删除文件。
特权
特权是用户在本地计算机上执行与系统相关的操作(例如加载驱动程序、更改时间或关闭系统)的权限。
特权与访问权不同,因为特权应用于与系统(而不是对象)相关的任务和资源,并且特权由系统管理员(而不是操作系统)授予用户或组。
每个进程的存取令牌都包含一个授予该进程的特权列表。
特权必须在使用之前专门启用。
管理员使用Windows控制面板中的管理工具来启用和审核特权的使用;也可以通过编程方式启用特权。
Topofpage
安全场景:
创建一个文件
当进程创建文件或对象的句柄时,系统使用“Windows安全模型”中阐述的安全构造。
图2显示当用户模式进程试图创建一个文件时触发的与安全相关的操作。
Clicktoviewfull-sizeimage.
图2.处理CreateFile请求
图2显示当用户模式应用程序调用CreateFile函数时系统如何响应。
下面对圆圈中的数字进行说明:
1.
用户模式应用程序调用CreateFile函数,传递一个有效的MicrosoftWin32文件名。
2.
用户模式Kernel32.dll将请求传递给Ntdll.dll,该DLL将Win32名称转换为MicrosoftWindowsNT文件名。
3.
Ntdll.dll使用WindowsNT文件名调用NtCreateFile函数。
在Ntoskrnl.exe内部,I/O管理器处理NtCreateFile。
4.
I/O管理器将请求重新打包成一个对象管理器调用。
5.
对象管理器解析符号链接,并确保用户对将在其中创建文件的路径具有遍历权限。
详细信息请参见本文稍后的“对象管理器中的安全检查”。
6.
对象管理器调用拥有与请求关联的底层对象类型的系统组件。
对于一个文件创建请求,该组件就是I/O管理器,它拥有设备对象。
7.
I/O管理器检查设备对象的安全描述符与用户进程的存取令牌,以确保用户具有所需的设备访问权。
详细信息请参见本文稍后的“I/O管理器中的安全检查”。
8.
如果用户进程具有所需的访问权,那么I/O管理器创建一个句柄并将一个IRP_MJ_CREATE请求发送到设备或文件系统的驱动程序。
9.
该驱动程序根据需要执行额外的安全检查。
例如,如果请求在设备的命名空间中指定了一个对象,那么驱动程序必须确保调用方具有所需的访问权。
详细信息请参见本文稍后的“驱动程序中的安全检查”。
对象管理器中的安全检查
检查访问权限的责任属于可以执行这类检查的最高层组件。
如果对象管理器能够验证调用方的访问权,那么它就是这个最高层组件。
否则,对象管理器将请求传递给负责底层对象类型的组件。
然后该组件验证访问权(如果它拥有验证权限);如果无法验证,它将请求传递给更底层的组件,例如驱动程序。
对象管理器检查简单对象类型(例如事件和互斥锁)的ACL。
对于具有命名空间的对象,由该类型的所有者执行安全检查。
例如,I/O管理器被认为是设备对象和文件对象类型的所有者。
如果对象管理器在解析名称时找到了设备对象或文件对象的名称,那么它将该名称传递给I/O管理器,正如“安全场景:
创建一个文件”中所示的文件创建场景一样。
然后I/O管理器检查访问权限(如果它具有该权限的话)。
如果该名称指定一个设备命名空间内部的对象,那么I/O管理器接下来会将名称传递给设备(或文件系统)驱动程序,该驱动程序负责验证请求的访问。
I/O管理器中的安全检查
当I/O管理器创建一个句柄时,它检查对象的权限和进程的存取令牌,然后将授予用户的权限存储为句柄的一部分。
在以后I/O请求到达时,I/O管理器检查句柄中记录的权限,以确保进程拥有执行请求的I/O操作的权限。
例如,如果进程在以后请求一个写操作,那么I/O管理器检查句柄中的权限以确保调用方具有对对象的写访问权。
如果句柄重复,那么可以从副本中删除权限,但是不能将权限添加到副本中。
当I/O管理器创建对象时,它将一般的Win32访问模式转换为对象特定的权限。
例如,以下权限适用于文件和目录。
Win32访问模式
对象特定的权限
GENERIC_READ
ReadData|ReadAttributes|ReadEA
GENERIC_WRITE
WriteData|WriteAttributes|WriteEA
GENERIC_EXECUTE
ReadAttributes|Execute/Traverse
GENERIC_ALL
所有权限
要创建一个文件,进程必须具有对目标路径中的父目录的遍历权限。
例如,要创建\Device\Floppy0\Directory\File.txt,进程必须具有遍历\Device、\Device\Floppy0和\Device\Floppy0\Directory的权限。
I/O管理器只检查这些目录的遍历权限。
I/O管理器在分析文件名时检查遍历权限。
如果文件名是一个符号链接,那么I/O管理器将其解析为完整的路径,然后从根目录开始检查遍历权限。
例如,假设符号链接\DosDevices\A映射为WindowsNT设备名\Device\Floppy0。
进程必须具有对\Device目录的遍历权限。
驱动程序中的安全检查
实际上,操作系统内核将每个驱动程序都视为具有其自己的命名空间的文件系统。
因此,当调用方试图在设备命名空间中创建对象时,I/O管理器就会检查进程是否具备对该路径中的目录的遍历权限。
但是,默认情况下,I/O管理器不对命名空间执行安全检查。
驱动程序负责保证其命名空间的安全性。
Topofpage
驱动程序安全责任
设备的驱动程序负责保证未授权用户没有对设备的访问权。
保证设备安全性涉及:
•
创建安全的设备对象。
•
保护设备命名空间。
•
在INF文件中指定设备特征和安全设置。
•
安全地定义和处理IOCTL。
创建安全的设备对象
每个设备对象都有一个安全描述符,它包含一个用于控制对设备的访问的ACL。
一般来讲,安全描述符是在创建设备对象的同时创建的,ACL是在设备的INF文件中指定的,但具体细节因驱动程序在设备堆栈中的位置和其控制的设备类型不同而异。
下面的章节描述以下驱动程序的特定要求:
•
总线驱动程序
•
其它即插即用和WindowsDriverModel(WDM)驱动程序
•
传统设备
总线驱动程序
可以在RAW模式下运行的设备的WDM总线驱动程序必须使用IoCreateDeviceSecure例程来创建其物理设备对象(PDO)并设置强壮的默认ACL。
例如,RAW模式设备PDO的ACL可以设置SDDL_DEVOBJ_SYS_ALL,这允许系统(SY)进行访问,但是拒绝其他所有人进行访问:
“D:
P(A;;GA;;;SY)”
这个ACL甚至会阻止管理员访问设备。
但是,设备的INF文件可以放宽ACL条件,以允许管理员或其他合法用户进行访问。
因为RAW模式设备无需INF文件就能启动,所以在创建设备对象时指定一个强壮的默认ACL非常关键。
否则,如果设备没有INF文件,那么用户无需进行任何安全检查就可以获得对设备的访问权。
如果设备不能在RAW模式下使用,那么驱动程序可以调用IoCreateDevice或IoCreateDeviceSecure例程来创建设备对象。
如果驱动程序使用IoCreateDevice,那么PnP管理器应用默认的安全描述符(正如它对其它WDM设备对象所做的一样)。
但是,如果PDO需要比默认设置更严格的安全检查,那么INF文件应该提供一个安全描述符。
即插即用和WDM驱动程序
即插即用(PnP)和WDM驱动程序(总线驱动程序除外,该驱动程序已在“总线驱动程序”中描述)调用IoCreateDevice例程来创建一个未命名的设备对象。
PnP管理器将一个默认的安全描述符应用于每一个这类未命名设备对象。
设备的INF文件应该指定设备特定的ACL。
PnP管理器确保将ACL应用于设备堆栈中的所有设备对象,从而在允许其它进程访问设备之前保护整个堆栈。
在INF文件中,ACL通过SDDL指定并包含在AddReg节中。
AddReg节还可以设置设备特征,例如FILE_DEVICE_SECURE_OPEN。
即插即用和WDM驱动程序不应使用IoCreateDeviceSecure例程来创建附加到设备堆栈的设备对象。
但是,一些即插即用驱动程序可以创建已命名控制设备对象,这类对象不会附加到设备堆栈。
必须使用IoCreateDeviceSecure例程来创建这类控制设备对象。
传统设备
传统设备指不受PnP管理器控制的设备。
传统驱动程序必须在\Device对象目录中创建至少一个已命名设备对象来接收I/O请求。
要保护传统设备的设备对象,其驱动程序必须调用IoCreateDeviceSecure例程来创建已命名设备对象,并为设备设置默认的安全描述符和类GUID。
安全描述符应该指定一个强壮的默认ACL,例如SDDL_DEVOBJ_SYS_ALL。
这项设置允许内核模式代码和用户模式代码以系统身份运行来访问设备对象。
在运行时,驱动程序的服务(以系统身份运行)可以使用SetFileSecurity用户模式函数将设备向用户打开。
保护设备命名空间
驱动程序在调用方试图打开设备命名空间中的对象时检查安全性。
调用方可以使用下列任一种格式来指定对象。
路径
描述
\Device\设备名称
设备名称的设备对象
\Device\设备名称\
设备名称上的顶级目录
\Device\设备名称\文件
设备名称上的文件
I/O管理器被视为设备对象的类型所有者;因此,I/O管理器负责在调用方以“\Device\设备名称”的形式指定名称时检查安全性。
驱动程序被视为其命名空间中的对象的类型所有者。
命名空间包含设备的顶级目录(\Device\设备名称\)和属于该目录的任何对象(\Device\设备名称\文件)。
安全地打开设备
用户通过指定设备名称来打开设备。
例如:
\Device\Serial0
当I/O管理器接收到打开请求时,它解析目标设备名称并检查进程存取令牌中的权限和目标设备对象的ACL。
通过拒绝对其设备对象的遍历权限,驱动程序可以拒绝对其设备的所有访问。
如果一个设备堆栈具有两个已命名设备对象,那么进程可以使用其中任何一个来打开设备堆栈。
在这种情况下,针对其中任何一个设备对象的IRP都被发送到同一个堆栈,所以两个设备对象的ACL必须同意这些IRP。
作为一般规则,PDO应该是堆栈中唯一的已命名设备对象。
如无必要,驱动程序不应该命名FDO,但是有一些例外。
例如,含有卷参数块(VolumeParameterBlock,VPB)的存储设备的FDO必须具有一个名称。
独占设备是同一时间只能为其打开一个句柄的设备。
WDM驱动程序在INF文件的AddReg指令中将设备指定为独占。
使用AddReg指令,系统将设置设备对象的Flags字段中的DO_EXCLUSIVE位。
如果设置了DO_EXCLUSIVE,那么I/O管理器通过检查设备命名空间的打开请求来以独占的方式执行。
如果未设置DO_EXCLUSIVE,则I/O管理器不会检查设备命名空间的打开请求;而驱动程序必须进行检查。
然而,即使为设备对象设置了DO_EXCLUSIVE位,拥有设备堆栈句柄的应用程序仍然可能通过打开相对于现有句柄的""来获取另外的句柄。
要防止这个问题,驱动程序应该拒绝对相关文件对象的任何IRP_MJ_CREATE请求。
驱动程序应该按如下方式检查IRP_MJ_CREATE请求中的RelatedFileObject字段值:
if(IrpSp->FileObject->RelatedFileObject!
=NULL)
RelatedFileObject字段中的非空值表示另一个句柄已经打开。
如果这个值非空,驱动程序必须拒绝此请求。
安全地打开文件
下列形式的打开请求将指定设备命名空间中的文件或其它对象:
\Device\Floppy0\Readme.txt\Device\Mup\Server\Share\File.txt\Device\Serial0\
注意:
\Device\Serial0\中结尾的反斜杠表示设备Serial0上的顶级目录。
默认情况下,驱动程序负责检查其设备命名空间内对象的安全性。
如果驱动程序不支持设备命名空间,那么它应该在设备对象中设置FILE_DEVICE_SECURE_OPEN特性。
如果设置了这个标志,那么操作系统将设备对象的安全描述符应用于设备命名空间中所有打开的请求。
如果设备对象的ACL不允许访问,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 安全 模型 Read