精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
Apart from administrative and/or troubleshooting purposes, you never need a system Access Control list (I have not yet encountered an SACL other than for test purposes). Anyway, you can only set an SACL if you have the SeSecurityPrivilege enabled. If your object supports inheritance, just get the SACL from the parent. Otherwise, your SACL should be NULL or empty. Remember, if you generate an audit every time you access an object (particularly if you frequently access the object), your Security Event Log will fill up with information overload.除了行政和/或排除故障的目的,你永远需要一个系统访问控制列表(我还没有遇到过比对试验目的的SACL等)。无论如何,只有启用了SACL才能设置SACL SeSecurityPrivilege。如果您的对象支持继承,则只需从父级获取SACL。否则,您的SACL应该为NULL或为空。请记住,如果您每次访问对象时都生成审核(特别是如果您频繁访问该对象),则安全事件日志将充满信息直至过载。
To read and write an SACL, you will need to enable the SeSecurityPrivilege. Adding entries to an SACL is similar to creating a DACL.
要读写SACL,您需要启用SeSecurityPrivilege。将条目添加到SACL,这类似于创建DACL。
... pSacl.AddAuditAce(ATL::Sids::Users(), WRITE_DAC, true, false); ...
Figure 21: Adding a system access control entry to an SACL.
This section will cover securing a new object only. For a new object, the object by default has no owner. You can specify an owner by filling the Owner member of the security descriptor. A suggested new owner is you (you from your thread token) or your group. However, any user that has WRITE_OWNER access to the object can take ownership of it (and thus get full control to it).本节仅涉及保护新对象。对于新对象,默认情况下该对象没有所有者。您可以通过填充Owner安全描述符的成员来指定所有者。一个建议的新主人是你(你从你的线程令牌)或你的团体。但是,任何有权WRITE_OWNER访问该对象的用户都可以拥有该对象的所有权(因此可以完全控制该对象)。
Few apps read the Group part of the security descriptor, but just in case there are, this should be set to the primary group of your token—obtained from GetTokenInformation(TokenPrimaryGroup).很少有应用程序读取安全描述符的“组”部分,但是以防万一,应将其设置为令牌的主要组-从获取GetTokenInformation(TokenPrimaryGroup)。
The Control member is a collection of flags dumped into a 32 bit integer. Windows will use this parameter to determine which members of the security descriptor are valid. If you are securing an object that supports inheritance, there are extra flags you need to set in the Control member of the security descriptor. If you get one of the flags wrong in this member (e.g.. you say that the group is valid when it in fact isn't), then you may crash.所述控制构件是倾入一个32位整数标志位的集合。Windows将使用此参数来确定安全描述符的哪些成员有效。如果要保护支持继承的对象,则需要在安全描述符的成员中设置其他标志Control。如果您在该成员中得到错误的标志之一(例如,您说该组实际上是无效的,则说该组是有效的),那么您可能会崩溃。
To set these members, follow your chosen method:要设置这些成员,请遵循您选择的方法:
... OutSecDesc.SetOwner(ATL::Sids::Admins(), false); OutSecDesc.SetGroup(ATL::Sids::Admins(), false); ...
Figure 22: Finalizing the security descriptor for a new object.
The inheritance of a security descriptor appears in two places. Each ACE has an inheritance flag that specifies how inheritance is applied to child objects / containers. These flags (the IO, OI, CI, etc.) were described in part 1. This same flag also determines if an ACE came from a parent ACL (which you can detect with the INHERITED_ACE flag).安全描述符的继承出现在两个地方。每个ACE都有一个继承标志,用于指定如何将继承应用于子对象/容器。这些标志(的IO,OI,CI等)中进行了描述部分1。该相同标志还确定ACE是否来自父ACL(可以使用该INHERITED_ACE标志检测到)。
The Control member determines if the DACL and SACL auto-inherit ACEs from their parent. By setting the SE_DACL_AUTO_INHERITED | SE_DACL_AUTO_INHERIT_REQ control flags in a security descriptor, Windows will get the parent's DACL, attach it to the end of your DACL, and write this merged DACL to the object. These inherited ACLs cannot be edited—if you want to change something in the inherited ACL, you must either add in a deny ACE to override the inherited ACE, or stop inheriting.该Control成员决定是否从其父的DACL和SACL自动继承的ACE。通过SE_DACL_AUTO_INHERITED | SE_DACL_AUTO_INHERIT_REQ在安全描述符中设置控制标志,Windows将获取父级的DACL,将其附加到DACL的末尾,然后将此合并的DACL写入对象。这些继承的ACL无法编辑-如果要更改继承的ACL中的某些内容,则必须添加拒绝ACE来覆盖继承的ACE,或者停止继承。
To prevent inheritance, you must set your DACL to be protected (SE_DACL_PROTECTED). If you set this flag, only the explicit entries remain, meaning you may have to copy the parent's DACL into the object to get the old DACL.为了防止继承,您必须将DACL设置为保护(SE_DACL_PROTECTED)。如果设置此标志,则仅保留显式条目,这意味着您可能必须将父级的DACL复制到对象中才能获得旧的DACL。
If you have a protected DACL, and you want to stop it from being protected, you should empty the DACL, then set the SE_DACL_AUTO_INHERIT_REQ Control bit. This will disable DACL protection and enable auto-inheritance.如果您有受保护的DACL,并且想要停止对其进行保护,则应清空DACL,然后将SE_DACL_AUTO_INHERIT_REQ控制位置1。这将禁用DACL保护并启用自动继承。
The "AI" after the "D:" tells SDDL to set SE_DACL_AUTO_INHERITED in the Control bits. If instead of "AI", you had "P", then SE_DACL_PROTECTED will be set instead. The last flag, "AR", corresponds to SE_DACL_AUTO_INHERIT_REQ.
“ AI”之后的“ D:”告诉SDDL设置SE_DACL_AUTO_INHERITED控制位。如果AI您有“ P”SE_DACL_PROTECTED而不是“ ”,则将被设置。最后一个标志“ AR”对应于SE_DACL_AUTO_INHERIT_REQ。
... OutSecDesc.SetControl(SE_DACL_AUTO_INHERITED | SE_DACL_PROTECTED, SE_DACL_AUTO_INHERITED); ...
Figure 23: Supporting inheritance for security descriptors.
The inheritance rules for SACLs are the same as DACLs.
When you created a Windows object, you encountered a parameter asking for a SECURITY_ATTRIBUTES structure (unless you encountered a wrapper class / function for the resource). This is where you will supply the security descriptor for the new object. Note that some objects do not support all the features of security descriptors (particularly inheritance)--in this case, these extra features will be ignored (which could lead to inaccessible objects if you're not careful). Once you pass this parameter in, that should be it. How the security descriptor gets stored is the object's problem, not yours. However, to prevent surprises, you should ensure that the object is created (not merely opened). If the object already exists, then the security descriptor is not applied, and the security attributes are ignored.创建Windows对象时,遇到一个要求SECURITY_ATTRIBUTES结构的参数(除非遇到该资源的包装器类/函数)。您将在此处提供新对象的安全描述符。请注意,某些对象不支持安全描述符的所有功能(尤其是继承),在这种情况下,这些额外的功能将被忽略(如果不小心,可能会导致无法访问对象)。一旦传入此参数,就应该是它。安全描述符的存储方式是对象的问题,而不是您的问题。但是,为防止意外,应确保已创建对象(不仅仅是打开对象)。如果对象已经存在,则不应用安全描述符,并且忽略安全属性。
Generally, in order to access the SECURITY_ATTRIBUTES, you'll probably want to use the Win32 APIs directly. This is because most wrapper classes neglect the SECURITY_ATTRIBUTES parameter, and pass in NULL for this class. (CAtlFile is an exception, but by default, it passes in NULL too.)通常,为了访问SECURITY_ATTRIBUTES,您可能需要直接使用Win32 API。这是因为大多数包装器类都忽略了SECURITY_ATTRIBUTES参数,并NULL为此类传递了参数。(这CAtlFile是一个例外,但默认情况下NULL也会通过。)
if(::GetFileAttributes(FileName) == INVALID_FILE_ATTRIBUTES) { SECURITY_ATTRIBUTES lpSecurityAttributes = {sizeof(SECURITY_ATTRIBUTES), const_cast(OutSecDesc.GetPSECURITY_DESCRIPTOR()), FALSE}; ::SetLastError(ERROR_SUCCESS); /** We're going to use the low level Win32 APIs * instead of ATL::CAtlFile **/ ATL::CHandle FileHandle (::CreateFile(FileName, GENERIC_ALL | READ_CONTROL | WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &lpSecurityAttributes, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)); if( static_cast (FileHandle) == NULL || static_cast (FileHandle) == INVALID_HANDLE_VALUE) { throw ATL::CAtlException(HRESULT_FROM_WIN32(::GetLastError())); } } /* The else part will be handled in fig. 24. */
Figure 24: Creating an object that has a custom security descriptor.
This technique doesn't work if the object already exists. If you open an existing object, the security descriptor is ignored.
This question assumes you either know the name and type of the object you are securing, or you have a handle to that object. If you are securing an existing object, you can get away with creating an incomplete security descriptor (e.g.. a security descriptor without an owner or group). You tell Windows which parts of the security descriptor are valid by passing in a SECURITY_INFORMATION variable. For example, if you are just setting the DACL of an object, you can specify DACL_SECURITY_INFORMATION.这个问题假设您知道要保护的对象的名称和类型,或者您有该对象的句柄。如果要保护现有对象,则可以创建一个不完整的安全描述符(例如,没有所有者或组的安全描述符)。您可以通过传入SECURITY_INFORMATION变量来告诉Windows安全描述符的哪些部分有效。例如,如果仅设置对象的DACL,则可以指定DACL_SECURITY_INFORMATION。
If you cannot obtain a handle to the file (say, you don't have READ_CONTROL or WRITE_DAC access yet), you can call the similar SetNamedSecurityInfo() function to set the security for the file. However, the SetSecurityInfo() function can secure more objects than SetNamedSecurityInfo().如果你不能获得一个句柄的文件(比如说,你没有READ_CONTROL或WRITE_DAC访问还),你可以调用类似的SetNamedSecurityInfo()函数来设置该文件的安全性。但是,该SetSecurityInfo()功能可以保护的对象比的更多SetNamedSecurityInfo()。
SetNamedSecurityInfo() can set the security on the following objects:
SetNamedSecurityInfo() 可以对以下对象设置安全性:
For SetNamedSecurityInfo() to work, you have to split your security descriptor back into separate pieces. You can call GetSecurityDescriptorDacl() and friends to get these members (portably). One thing to note is that SetSecurityInfo() apparently doesn't allow you to set the control bits directly. Instead, you provide the control bits in the SECURITY_INFORMATION parameter. The Control bits to SECURITY_INFORMATION mapping is as follows:为了SetNamedSecurityInfo()工作,您必须将安全描述符拆分成单独的部分。您可以打电话GetSecurityDescriptorDacl()和朋友来获得这些成员(便携式)。需要注意的一件事是,SetSecurityInfo()显然不允许您直接设置控制位。而是在SECURITY_INFORMATION参数中提供控制位。SECURITY_INFORMATION映射的控制位如下:
Use this map to translate the control bits into SECURITY_INFORMATION flags. This new security descriptor will replace the old security descriptor. If this is not what you want (i.e. you want to add entries to the DACL rather than replace it), you have to merge the old entries with the new ones yourself, or you could apply auto-inheritance (these will be automatically applied onto the child).
If you have the rights, the security descriptor should get applied to the object with the correct inheritance settings and sorted entries. The Set*SecurityInfo() does not support NULL DACLs, and will fail if you attempt to set one.
使用此映射将控制位转换为SECURITY_INFORMATION标志。此新的安全描述符将替换旧的安全描述符。如果这不是您想要的(即,您想要将条目添加到DACL而不是替换它),则必须自己将旧条目与新条目合并,或者可以应用自动继承(这些将自动应用于孩子)。
如果您拥有权限,则应该使用正确的继承设置和排序的条目将安全描述符应用于对象。,Set*SecurityInfo()不支持NULLDACL,如果您尝试设置一个,它将失败。
... ATL::AtlSetDacl(FileName, SE_FILE_OBJECT, pDacl); ATL::CSacl pSacl; /* We've already set the Dacl. Now set the SACL. */ OutSecDesc.GetSacl(&pSacl, &pbPresent); if(pbPresent) { ATL::AtlSetSacl(FileName, SE_FILE_OBJECT, pSacl); } ATL::CSid pOwner, pGroup; if(OutSecDesc.GetOwner(&pOwner)) { ATL::AtlSetOwnerSid(FileName, SE_FILE_OBJECT, pOwner); } if(OutSecDesc.GetGroup(&pGroup)) { ATL::AtlSetGroupSid(FileName, SE_FILE_OBJECT, pGroup); } ...
Figure 25: Applying the security descriptor to an existing object
In order for SetSecurityInfo() to succeed, you must have the WRITE_DAC right to set the DACL and WRITE_OWNER rights to set the owner. If you were denied the WRITE_OWNER | WRITE_DAC right, you can acquire these by taking ownership of the file. Enabling the SeTakeOwnershipPrivilege will allow you to take ownership of the file (even if WRITE_OWNER was disabled).
Although the Set*SecurityInfo() functions work with almost all of the Windows built-in objects (and even some special objects), you may want to implement security descriptors for your own classes.为了SetSecurityInfo()成功,您必须具有WRITE_DAC设置DACL的WRITE_OWNER权限和设置所有者的权限。如果您被拒绝使用该WRITE_OWNER | WRITE_DAC权利,则可以通过获取文件所有权来获取这些权利。启用SeTakeOwnershipPrivilege将允许您取得文件的所有权(即使WRITE_OWNER已禁用)。
尽管这些Set*SecurityInfo()函数可用于几乎所有Windows内置对象(甚至某些特殊对象),但是您可能希望为自己的类实现安全描述符。