第六章 确定适当的访问控制PPT讲稿.ppt
第六章 确定适当的访问控制第1页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制1ACL的重要性l下面的代码从具有危险ACL的注册表项中读取数据:#define MAX_BUFF 64#define MY_VALUE“SomeData”BYTE bBuffMAX_BUFF;ZeroMemory(bBuff,MAX_BUFF);/Open the registry./Open the registry.HKEY hKey=NULL;If(RegOpenKeyEx(HKEY_LOCAL_MACHINE,”SoftwareNorthwindtraders”,0,KEY_READ,&hKey)=ERROR_SUCCESS)/Determine how much data to read./Determine how much data to read.DWORD cbBuff=0;if(RegQueryValueEx(hKey,MY_VALUE,NULL,NULL,NULL,&cbBuff)=ERROR_SUCCESS)/Now read all the data./Now read all the data.if(RegQueryValueEx(hKey,MY_VALUE,NULL,NULL,bBuff,&cbBuff)=ERROR_SUCCESS/Cool!/We have read the data from the registry.If(hKey)RegCloseKey(hKey);第2页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制RegOpenKeyEx函数函数用于打开指定的注册表键(Key).注意注意:键名不区分大小写键名不区分大小写.语法语法LONG WINAPI RegOpenKeyEx(_in HKEY hKey,_in_opt LPCTSTR lpSubKey,_reserved DWORD ulOptions,_in REGSAM samDesired,_out PHKEY phkResult);参数表参数表hKey需要打开的键的句柄.该句柄可以来自于 RegCreateKeyEx 或 RegOpenKeyEx 函数,或者是以下预定义键之一:HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS lpSubKey 希望打开的子键(subkey)名,该名称不区分大小写.如果这个参数为NULL或一个指向空字符串的指针,函数将创建一个新的关联于hkey参数所指键的句柄.需要更多信息,查看Registry Element Size Limits(注册表项大小限制)ulOptions这个参数是预留的这个参数是预留的,它必须为它必须为0.samDesired指明希望使用何种权限打开该键.如果安全配置并不允许所希望的权限,函数调用将会失败.需要更多信息,查看Registry Key Security and Access Rights(注册表安全与存取权限).phkResult一个指向接受所打开键句柄变量的指针.如果该键不是预定义的,当你不再使用这个句柄时,调用 RegCloseKey函数.返回值返回值如果函数调用成功,返回值ERROR_SUCCESS.否则,函数将返回一个定义于 Winerror.h 的非零错误码.头文件 在Winreg.h声明;包含于(inculde)Windows.h.库 使用 Advapi32.lib.DLL Advapi32.dll.第3页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制RegQueryValueEx找回所打开注册表键所关联的一个给定值的类型和数据。LONG RegQueryValueEx(HKEY hKey,/要查询键的句柄 LPTSTR lpValueName,/要查询值的名字的地址 LPDWORD lpReserved,/保留 LPDWORD lpType,/值类型缓存地址 LPBYTE lpData,/数据缓存地址 LPDWORD lpcbData/数据缓存大小地址);参数参数hKey 一个当前已打开键的句柄lpValueName 指向要查询值的名字的字符串(以空字符结束)。如果lpValueName是NULL或一个空字符串(),这个函数找回这个键的未命名或默认值的类型和数据。lpReserved 保留,必须是NULL.lpType 指向与给定值相关联数据的类型的变量。这个值将通过这个参数返回,将是下面之一:值 含意 REG_BINARY 二进制数据。REG_DWORD 一个32位数字。REG_DWORD_LITTLE_ENDIAN 一个little-endian格式的32位数字。REG_DWORD_BIG_ENDIAN 一个big-endian格式的32位数字。REG_EXPAND_SZ 一个包含未被引用的环境变量的以空字符结束的字符串(如,%PATH%)。REG_LINK 一个Unicode符号连接。REG_MULTI_SZ 一个以空字符结束的字符串数组,被两个null字符结束。REG_NONE 未定义值类型。REG_RESOURCE_LIST 一个设备驱动资源列表。REG_SZ 一个以空字符结束的字符串。如果不需要类型lpType参数可以为空(NULL)。lpData 指定接收值数据的缓存区。如果数据是不需要的这个参数可以为空。lpcbData 以字节为单位,指向lpData参数所指定地缓存区大小的变量。函数返回复制到lpData的数据大小的变量。如果数据是REG_SZ、REG_MULTI_SZ或REG_EXPAND_SZ类型,那么lpcbData还将包括以空字符结束的大小。如果lpData是NULL,lpcbData参数可以是NULL。如果被lpData参数指定的缓存不够大,这个函数返回ERROR_MORE_DATA值,并取回被lpcbData指定的变量缓存的大小(以字节为单位)。如果lpData是NULL,lpcbData不是NULL,这个函数返回ERROR_SUCCESS,并取回被lpcbData指定的变量缓存的大小(以字节为单位)。这个为值的数据缓存分配最好的途径。返回值返回值如果这个函数成功,返回ERROR_SUCCESS。如果调有失败,返回一个非零错误码(定义在WINERROR.H)。第4页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制1ACL的重要性上述代码错误地假设注册表中的数据大小不超过64字节。其中第一次调用RegQueryValueEx从注册表中读取数据大小,而第二次调用RegQueryValueEx将根据第一次调用所确定的字节大小将数据读入本地缓冲区。如果数据大小超过64字节的话,将发生潜在的缓冲区溢出。注册表项的ACL决定了潜在的威胁。如果ACL是Everyone(完全控制),由于任何用户都可以对注册表项设置一个大于64字节的数据,造成该程序缓冲区溢出,所以这种潜在的威胁非常严重。此外,攻击者可以将这个ACL设置为Everyone(全部拒绝),这将拒绝你的应用程序对该数据的访问。如果这个ACL是Administrators(完全控制)和Every(读取),由于只有管理员可以设置注册表项上的数据或更改ACL,所以这样带来的威胁就不太严重。第5页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制1ACL的重要性l对代码的修复/Determine how much data to read.DWORD cbBuff=0;if(RegQueryValueEx(hKey,MY_VALUE,NULL,NULL,NULL,&cbBuff)=ERROR_SUCCESS)BYTE*pbBuff=new BYTEcbBuff;/Now read cbBuff bytes of data.if(pbBuff&RegQueryValueEx(hKey,MY_VALUE,NULL,NULL,pbBuff,&cbBuff)=ERROR_SUCCESS)/Cool!/We have read the data from the registry./use data.delete pbBuff;这段代码仍然有问题,但是性质已经不同。如果攻击者可以往注册表中写入10M数据的话,由于ACL存在的缺陷,使得攻击者强制你的应用程序分配10M的内存。第6页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制1ACL的重要性l对代码的进一步修复BYTE bBuffMAX_BUFF;ZeroMemory(bBuff,MAX_BUFF);HKEY hKey=NULL;if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,“SoftwareNorthwindtraders”,0,KEY_READ,&hKey)=ERROR_SUCCESS)DWORD cbBuff=sizeof(bBuff);/now read no more than MAX_BUFF bytes of data.if(RegQueryValueEx(hKey,MY_VALUE,NULL,NULL,bBuff,&cbBuff)=ERROR_SUCCESS)/Cool!/We have read the data from the registry.If(hKey)RegCloseKey(hKey);这种情况下,即使攻击者在注册表中放入一个大数据,这段代码也只读到MAX_BUFF个字节为止,如果还存在更多的数据的话,RegQueryValueEx将返回一个ERROR_MORE_DATA错误,指出这个缓冲区不足以容纳整个的数据。第7页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制2ACL的组成ACL是许多操作系统使用的一种访问控制方法,这些操作系统借助于ACL来判断一个账户对一个资源具有何种程度的访问权限。Windows NT及其后来的版本具有两种类型的ACL:DACL(Discretionary access control list,自由选定访问控制表)和SACL(System access control list,系统访问控制表)。DACL用来确定对安全资源的访问权限;SACL用来确定对安全资源的审核策略。第8页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制2ACL的组成l判断文件系统是否支持ACL#include#include Void main()char*szVol=“c:”;DWORD dwFlags=0;if(GetVolumeInformation(szVol,NULL,0,NULL,NULL,&dwFlags,NULL,0)printf(“Volume%s does%s support ACLs.”,szVol,(dwFlags&FS_PERSISTENT_ACLS)?“”:”not”);elseprintf(“Error%d”,GetLastError();/*GetVolumeInformation(lpRootPathName:PChar;磁盘驱动器代码字符串lpVolumeNameBuffer:PChar;磁盘驱动器卷标名称nVolumeNameSize:DWORD;磁盘驱动器卷标名称长度lpVolumeSerialNumber:PDWORD;磁盘驱动器卷标序列号var lpMaximumComponentLength:DWORD;系统允许的最大文件名长度var lpFileSystemFlags:DWORD;文件系统标识lpFileSystemNameBuffer:PChar;文件操作系统名称nFileSystemNameSize:DWORD 文件操作系统名称长度);*/第9页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制2ACL的组成l可以使用DACL来进行安全化或者使用SACL进行审核的资源如下:文件和目录文件共享注册表项共享的内存作业对象互斥量(Mutex)命名管道打印机信号量(Semaphore)活动目录对象第10页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制2ACL的组成lDACL组成(*)每个DACL可以包括零个或多个ACE(Access Control Entries,访问控制项),一个NULL DACL意味着在相应的资源上没有访问控制。一个ACE包括两个主要的组件:由该帐户的安全标识符(Security ID,SID)所表示的一个账户,以及关于这个SID可以对给定资源进行哪些操作的描述。第11页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制3选择好的ACL的方法为你的资源定义合适的ACL的过程:(1)确定你使用的资源。需要使用哪些资源以及对哪些资源进行保护。(2)确定业务上定义的访问需求。(3)确定适当的访问控制技术。(4)将访问需求转换为相应的访问控制技术。如下面是某一资源的ACL:主体主体访问权限访问权限Accounting拒绝所有访问Interactive Users读Administrators完全控制SYSTEM完全控制第12页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACL/*NT4ACL.CPP*/#include#include#include PSID pEveryoneSID=NULL,PAdminSID=NULL,pNetworkSID=NULL;PACL pACL=NULL;PSECURITY_DESCRIPTOR pSD=NULL;/ACL will contain three ACEs:/Network(Deny Access)/Everyone(Read)/Admin(Full Control)try const int NUM_ACES=3;EXPLICIT_ACCESS eaNUM_ACES;ZeroMemory(&ea,NUM_ACES*sizeof(EXPLICIT_ACCESS);/Create a well-known SID for the Network logon group.SID_IDENTIFIER_AUTHORITY SIDAuthNT=SECURITY_NT_AUTHORITY;if(!AllocateAndInitializeSid(&SIDAuthNT,1,SECURITY_NETWORK_RID,0,0,0,0,0,0,0,&pNetworkSID)throw GetLastError();BOOL AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,/pointer to identifier authorityBYTE nSubAuthorityCount,/count of subauthoritiesDWORD dwSubAuthority0,/subauthority 0DWORD dwSubAuthority1,/subauthority 1DWORD dwSubAuthority2,/subauthority 2DWORD dwSubAuthority3,/subauthority 3DWORD dwSubAuthority4,/subauthority 4DWORD dwSubAuthority5,/subauthority 5DWORD dwSubAuthority6,/subauthority 6DWORD dwSubAuthority7,/subauthority 7PSID*pSid/pointer to pointer to SID);第13页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACLea0.grfAccessPermissions=GENERIC_ALL;ea0.grfAccessMode=DENY_ACCESS;ea0.grfInheritance=NO_INHERITANCE;ea0.Trustee.TrustForm=TRUSTEE_IS_SID;ea0.Trustee.TrustType=TRUSTEE_IS_WELL_KNOWN_GROUP;ea0.Trustee.ptstrName=(LPTSTR)pNetworkSID;/Create a well-known SID for the Everyone group.SID_IDENTIFIER_AUTHORITY SIDAuthWorld=SECURITY_World_SID_AUTHORITY;if(!AllocateAndInitializeSid(&SIDAuthWorld,1,SECURITY_WORLD_RID,0,0,0,0,0,0,0,&pEveryoneSID)throw GetLastError();ea1.grfAccessPermissions=GENERIC_READ;ea1.grfAccessMode=SET_ACCESS;ea1.grfInheritance=NO_INHERITANCE;ea1.Trustee.TrustForm=TRUSTEE_IS_SID;ea1.Trustee.TrustType=TRUSTEE_IS_WELL_KNOWN_GROUP;ea1.Trustee.ptstrName=(LPTSTR)pEveryoneSID;第14页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACL/Create a SID for the BUILTIN/Administrators group.if(!AllocateAndInitializeSid(&SIDAuthNT,2,SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS,0,0,0,0,0,0,&pAdminSID)throw GetLastError();ea2.grfAccessPermissions=GENERIC_ALL;ea2.grfAccessMode=SET_ACCESS;ea2.grfInheritance=NO_INHERITANCE;ea2.Trustee.TrustForm=TRUSTEE_IS_SID;ea2.Trustee.TrustType=TRUSTEE_IS_GROUP;ea1.Trustee.ptstrName=(LPTSTR)pAdminSID;/Create a new ACL with the three ACEs.if(ERROR_SUCCESS!=SetEntriesInAcl(NUM_ACES,ea,NULL,&pACL)throw GetLastError();/Initialize a security descriptor.pSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);if(pSD=NULL)throw GetLastError();if(!InitializeSecurityDescriptor(pSD,SECURITY_DESCRIPTOR_REVISION)throw GetLastError();InitializeSecurityDescriptor()函数初始化一个新的安全描述符。BOOL InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor,/安全描述符地址DWORD dwRevision/修订级别);参数:pSecurityDescriptor:一个指向函数初始化SECURITY_DESCRIPTOR结构的指针。dwRevision:指定分配给安全描述符的修订级别。它必须指定为SECURITY_DESCRIPTOR_REVISION。第15页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACL/Add the ACL to the security descriptor.if(!SetSecurityDescriptorDacl(pSD,TRUE,pACL,FALSE)throw GetLastError();elseSECURITY_ATTRIBUTES sa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.bInheritHandle=FALSE;sa.lpSecurityDescriptor=pSD;if(!CreateDirectory(“C:Program FilesMyStuff”,&sa)throw GetLastError();/End try catch()/Error condition第16页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACLif(pSD)LocalFree(pSD);if(pACL)LocalFree(pACL)/Call FreeSid for each SID allocated by AllocateAndInitializeSID.if(pEveryoneSID)FreeSid(if(pEveryoneSID);if(pNetworkSID)FreeSid(if(pNetworkSID);if(pAdminSID)FreeSid(if(pAdminSID);第17页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACL创建一个ACL后,不是将一个ACL直接应用在一个对象上,而是应用到一个SD(Security Descriptor,安全描述符)上,再将该SD应用到对象上。SD封装在一个SECURITY_ATTRIBUTES结构中,该结构包含有一个字段,用来判断这个SD是否是由相应进程继承而来。一个安全描述符中的信息描述了一个对象安全方面的下列几个部分:一个所有者(由一个SID表示),使用SetSecurityDescriptorOwner来设置。一个主要的组(由一个SID表示),使用SetSecurityDescriptorGroup来设置。一个DACL,使用SetSecurityDescriptorDacl来设置。一个SACL,使用SetSecurityDescriptorSacl来设置。如果缺少安全描述符中的任何一个部分,则使用默认值,默认的所有者与调用该函数的进程的身份相同。第18页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows NT 4中创建ACL创建一个ACL的过程:(*)SIDSID许可权EXPLICIT_ACCESSEXPLICIT_ACCESS许可权ACLSECURITY_DESCRIPTORSECURITY_ATTRIBUTES资源应用到资源第19页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACL(*)Windows 2000安全工程小组添加了一种ACL和安全描述符的文本化表示方式,称作安全描述语言(SDDL,Security Descriptor Definition Language)。在SDDL中,SID和ACE都是通过一些规范定义的文字来表示的。实例:下面的示例代码创建了一个C:MyDir的目录,并设置了下面的ACE:Guests(拒绝访问)SYSTEM(完全控制)Administrators(完全控制)Interactive Users(读、写和执行)第20页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACL/*SDDLACL.cpp*/#define _WIN32_WINNT 0 x500#include#include void main()SECURITY_ATTRIBUTES sa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.bInheritHandle=FALSE;char*szSD=“D:P”/DACL“(D;OICI;GA;BG)”/Deny Guests“(A;OICI;GA;SY)”/Allow SYSTEM Full Control“(A;OICI;GA;BA)”/Allow Admins Full Control“(A;OICI;GRGWGX;IU”;/Allow Interactive Users RWXif(ConvertStringSecurityDescriptorToSecurityDescriptor(szSD,SDDL_REVISION_1,&(sa.lpSecurityDescriptor),NULL)if(!CreateDirectory(“C:MyDir”,&sa)DWORD err=GetLastError();LocalFree(sa.lpSecurityDescriptor);第21页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACL(*)SDDL组件组件注释注释D:PD是一个DACL,如果是S,则为SACL。P选项设置了SE_DACL_PROTECTED,使你对该对象ACE具有最大的控制权,防止其父容器的ACE传递到该对象。如果不在乎从父对象继承ACE,可以去掉此选项。(D;OICI;GA;BG)一个ACE字符串。每个ACE都括在一个括符中。D=拒绝ACE。OICI=执行对象和容器继承,即这个ACE将自动设置到本对象或容器之下的对象和容器上。GA=常规的全部访问(完全控制)。BA=Guests组。这个ACE将阻止guest账户访问本目录及在本目录之下创建的文件或子目录。其中缺少的两个值分别是ObjectTypeGuid和InheritedObjectTypeGuid。(A;OICI;GA;SY)A=允许ACE。SY=SYSTEM账户。(A;OICI;GA;BA)BA=Administrators组。(A;OICI;GRGWGX;IU)GR=读,GW=写,GX=执行,IU=Interactive Users第22页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACLSDDL字符串的一般布局:(*)D:(D;OICI;GA;BG)(A;OICI;GA;SY)(A;OICI;GA;BA)(A;OICI;GRGWGX;IU)DACLACE允许或拒绝继承标志委托人ACE掩码第23页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACLSID类型:SDDL字字符串符串账户名称账户名称AOAccount OperatorsAUAuthenticated UsersBABuiltin AdministratorsBGBuiltin GuestsBOBackup OperatorsBUBuiltin UsersCACertificate Server AdministratorsCOCreator OwnerDADomain AdministratorsDGDomain Guests第24页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACLSID类型:SDDL字字符串符串账户名称账户名称DUDomain UsersIUInteractively Logged_on UsersLALocal AdministratorsLGLocal GuestsNUNetwork Logon UsersPOPrinter OperatorsPUPower UsersRCRestricted Code(受限的代码)SOServer OperatorsSUService Logon User第25页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl在windows 2000中创建ACLSID类型:SDDL字字符串符串账户名称账户名称SYLocal SYSTEMWDWorld(每个人通用)NSNetwork Service(Windows XP以上版本)LSLocal Service(Windows XP以上版本)ANAnonymous Logon(Windows XP以上版本)RDRemote Desktop and Terminal Server Users(Windows XP以上版本)NONetwork Configuration Operators(Windows XP以上版本)LULogging Users(Windows Server 2003以上版本)MUMonitoring Users(Windows Server 2003以上版本)第26页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl用活动模板库(ATL)创建ACL活动模板库是一组基于模板的C+类,包含在Microsoft Visual Studio 6和Visual Studio.NET中。在Visual Studio.NET中还加入了一组与安全相关的ATL类,用来更加方便地管理常规的Windows安全任务,包括ACL和安全描述符等。实例:用Visual Studio.NET的ATL创建一个目录,并为该目录分配一个ACL。这个ACL是:Blake(读)Administrators(完全控制)Guests(拒绝访问)第27页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制4创建ACLl用活动模板库(ATL)创建ACL/*ATLACL.cpp*/#include#include using namespace std;void main()try/the user accountsCSid sidBlake(“Northwindtradersblake”);CSid sidAdmin=Sids:Admins();CSid sidGuests=Sids:Guests();/Create the ACL,and populate with ACEs./note the deny ACE is placed before the allow ACEs.CDacl dacl;dacl.AddDeniedAce(sidGuests,GENERIC_ALL);dacl.AddAllowedAce(sidBlake,GENERIC_READ);dacl.AddDeniedAce(sidAdmin,GENERIC_ALL);/Create the Security descriptor and attributes.CSecurityDesc sd;sd.SetDacl(dacl);CSecurityAttributes sa(sd);/if(CreateDirectory(“C:MyTestDir”,&sa)cout“Directory created!”end1;catch(CAtlException e)cerr “Error,Application failed with error”hex (HRESULT)e end1;第28页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制5对ACE进行正确的排序当你的代码读取某资源如注册表项的ACL,添加ACE,然后更新注册表时,需要正确地排列ACE的顺序。如果在代码中创建ACL,正确的ACE顺序是:显式拒绝;显式允许;从父对象继承拒绝;从父对象继承允许;从祖父对象继承拒绝;从祖父对象继承允许;从曾祖父对象继承拒绝;从曾祖父对象继承允许,等等。第29页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制5对ACE进行正确的排序正确地向现有的ACL添加新的ACE,应执行下列步骤:使用GetSecurityInfo或GetNamedSecurityInfo函数从对象的安全描述符中获取现有的ACL。对每个新的ACE,用描述该ACE的信息填充一个EXPLICIT_ACCESS结构。调用SetEntriesInAcl,为新的ACE指定现有的ACL和EXPLICIT_ACCESS结构。调用SetSecurityInfo或SetNamedSecurityInfo函数,将新的ACL连接到对象的安全描述符上。下面的C+代码描述了此过程。第30页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制5对ACE进行正确的排序/*SetUpdatedACL.cpp*/#include“windows.h”#include“aclapi.h”#include Int main(int argc,char*argv)char*szName=“c:junkdata.txt”;PACL pDacl=NULL;PACL pNewDacl=NULL;PSECURITYDESCRIPTOR sd=NULL;PSID sidAuthUsers=NULL;DWORD dwErr=0;trydwErr=GetNamedSecurityInfoGetNamedSecurityInfo(szName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,&pDacl,NULL,&sd);if(dwErr!=ERROR_SUCCESS)throw dwErr;第31页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制5对ACE进行正确的排序EXPLICIT_ACCESS ea;ZeroMemory(&ea,sizeof(EXPLICIT_ACCESS);DWORD cbSid=SECURITY_MAX_SID_SIZE;sidAuthUsers=LocalAlloc(LMEM_FIXED,cbSid);if(sidAuthUsers=NULL)throw ERROR_NOT_ENOUGH_MEMORY;if(!CreateWellKnownSid(WinAuthenticatedUserSid,NULL,sidAuthUsers,&cbSid)throw GetLastError();BuildTrusteeWithSid(&ea.Trustee,sidAuthUsers);ea.grfAccessPermissions=GENERIC_READ;ea.grfAccessMode=SET_ACCESS;ea.grfInheritance=NO_INHERITANCE;ea.Trustee.TrusteeForm=TRUSTEE_IS_SID;ea.Trustee.TrusteeType=TRUSTEE_IS_GROUP;dwErr=SetEntriesInAclSetEntriesInAcl(1,&ea,pDacl,&pNewDacl);if(dwErr!=ERROR_SUCCESS)throw dwErr;第32页,共33页,编辑于2022年,星期三第六章 确定适当的访问控制5对ACE进行正确的排序dwErr=SetNamedSecurityInfoSetNamedSecurityInfo(szName,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNew