Windows 的访问控制
Copyright © MikeFeng
安全级别:基于NT
内核的Windows
是C2
级别的。
c2是俗称橘皮书(orange book)规格中的一个安全级别。橘皮书(the orangebook)是美国国家安全局(nsa)的国家计算机安全中心(ncsc)于1983年8月颁发的官方标准,其正式名称是“受信任计算机系统评量基准(trusted computer system evaluation criteria)",其封面为橘黄色,以此得名.橘皮书是目前颇具权威的计算机系统安全标准之一,ncsc也负责进行计算机系统及相关产品的安全测试.
橘皮书中对可信任系统的定义是这样的:一个由完整的硬件及软件所组成的系统,在不违反访问权限的情况下,它能同时服务于不限定个数的用户,并处理从一般机密到最高机密等不同范围的信息。更进一步,橘皮书将一个计算机系统可接受的信任程度加以分级,凡符合某些安全条件、基准、规则的系统即可归类为某种安全等级。橘皮书将计算机系统的安全性能由高而低划分为a、b、c、d四大等级,特别是较高等级的安全范围涵盖较低等级的安全范围,而每个大等级又以安全性高低依次编号细分成数个小等级,其中:
d——最低保护(minimal protection),凡没有通过其他安全等级测试项目的系统即属于该级,如ibm-pc、apple macintosh等个人计算机的系统虽未经安全测试,但如果有,很可能属于此级。
c——自定式保护(discretionary protection),该等级的安全特点在于系统的对象(如文件、目录)可由西的主题(如系统管理员、拥护、应用程序)自定义访问权。例如管理员可以决定某个文件仅允许一特定用户读取、另一用户写入。张三可以决定他的某个目录可公开给其他用户读、写等等。在unix、windows nt等操作系统都可以见到这种属性。该等级又依安全低、高分为c1、c2两个安全等级。
b——强制式保护(mandatory protection),该等级的安全特点在于由系统强制的安全保护,在强制式保护模式中,每个系统对象(如文件、目录等资源)及主题(如系统管理员、用户、应用程序)都有自己的安全标签(security label),系统即依据用户的安全等
级赋予他对各对象的访问权限。
a——可验证之保护(verified protection),虽然橘皮书仍可能定义比a1高的安全等级,但目前此级仅有a1等级,a等级的功能基本上与b3的相同,而其特点在于a等级的系统拥有正式的分析及数学式方法可完全证明该系统的安全策略及安全规格的完整性与一致性。
windows nt 3.51+号称具有c2安全等级,但windows nt 4.0及以上版本目前具有c2安全等级是毫无疑问的。换句话说,它的安全特性就是在于自定式保护(discretionary protection),nt未来可能提高到b2安全等级。
以下内容均针对Windows
- 安全描述符:内含安全信息。
- 安全对象:一个有安全描述符的对象。在很多Windows API中都传递安全对象,例如CreateFile
- 访问控制模型:一个可以控制进程去访问安全对象的模型。
- 访问tokens:一个登陆用户的安全信息。
- 访问权限和访问掩码:访问掩码是一组32位的信息,其中每一位都定义了一种访问权限。
- Trustee:ACE应用的对象,可以是一个用户帐户,组帐户或者是登陆Session。
- ACE:Access Control Entry。可以包含一个SID,访问掩码,ACE类型,一些标识位。有三种类型的ACE:用于DACL的禁止访问ACE和允许访问ACE,用户SACE的系统监察ACE
- ACL:ACE的列表。有两类ACL:DACL和SACL
- DACL:是否允许访问某个安全对象的ACL列表
- SACL:是否需要记录用户访问的ACL列表
创建一个安全对象的过程中有关安全描述符的部分:将创建是用户定义的安全描述符号赋值给新的对象,或者使用默认的安全描述符。应用在访问时获得这个安全对象,并加以分析,以确定自己是否有权限访问。
检查DACL的过程:分析其中的每一个ACL并累积结果,最终权限将应用于访问。
NULL DACL:如果一个安全描述符被设定为NULL,那么将默认获得所有权限
Empty DACL:如果一个DACL是空的,那么默认将没有任何权限
更改一个DACL的过程:
-
获得一个安全对象的DACL。调用GetNamedSecurityInfo函数;
-
创建一个Explicit_Accsse,简称ea;
-
将这个ea作为ACE和原来的ACL的内容设定进入一个新的DACL;
-
重新将这个ACL设定给安全对象。
示例函数:
int
SetAccess
(LPSTR FileName)
{
BOOL bSuccess = FALSE; // assume failure
DWORD dwError;
ExistingDacl = NULL;
NewAcl = NULL;
psd = NULL;
printf("Operations on %s ... ",FileName);
// get current Dacl on specified file
if (Maintian==1)
{
dwError = GetNamedSecurityInfo(
FileName,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
&ExistingDacl,
NULL,
&psd
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("GetNamedSecurityInfo");
return RTN_ERROR;
}
}
BuildExplicitAccessWithName(
&ea,
TrusteeName,
AccessMask,
option,
InheritFlag
// CONTAINER_INHERIT_ACE INHERIT_ONLY_ACE NO_PROPAGATE_INHERIT_ACE
// OBJECT_INHERIT_ACE SUB_CONTAINERS_AND_OBJECTS_INHERIT
// SUB_CONTAINERS_ONLY_INHERIT SUB_OBJECTS_ONLY_INHERIT
); // NO_INHERITANCE
// add specified access to the object
dwError = SetEntriesInAcl(
1,
&ea,
ExistingDacl,
&NewAcl
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("SetEntriesInAcl");
goto cleanup;
}
// apply new security to file
dwError = SetNamedSecurityInfo(
FileName,
SE_FILE_OBJECT, // object type
DACL_SECURITY_INFORMATION,
NULL,
NULL,
NewAcl,
NULL
);
if(dwError != ERROR_SUCCESS) {
DisplayLastError("SetNamedSecurityInfo");
goto cleanup;
}
bSuccess = TRUE; // indicate success
printf("successful/n",FileName);
cleanup
:
if( NewAcl != NULL ) AccFree( NewAcl );
if( psd != NULL) AccFree( psd );
if( ExistingDacl!= NULL) AccFree(ExistingDacl);
if(!bSuccess)
return RTN_ERROR;
return RTN_OK;
}