条件ACE(Conditional ACE)是一种特殊类型的ACE,在之前的文章中没有介绍过,现在介绍什么是条件ACE,以及SDDL中有关条件ACE的语法规定。
条件ACE是可以设置访问策略的ACE,通过在访问检查时计算策略设定的条件来决定是否做进一步的访问检查,从而实现更加个性化的访问控制,实际上就是为访问控制引入更多的决策因素,参考更广泛的控制条件。
条件ACE是回调(CALLBACK)ACE的一种形式,其中包含了特殊格式的应用数据(ApplicationData)字段,在该字段包含了在访问检查时运行的条件语句。条件ACE的格式如下:
AceType;AceFlags;Rights;ObjectGuid;InheritObjectGuid;AccountSid;ApplicationData
以下ACE类型可以作为条件ACE(列于上一篇ACE类型表中)
- ACCESS_ALLOWED_CALLBACK_ACE
- ACCESS_ALLOWED_CALLBACK_OBJECT_ACE
- ACCESS_DENIED_CALLBACK_ACE
- ACCESS_DENIED_CALLBACK_OBJECT_ACE
- SYSTEM_AUDIT_CALLBACK_ACE
- SYSTEM_AUDIT_CALLBACK_OBEJCT_ACE
在这些ACE中,如果ApplicationData字段以Ox61,0x72,0x74,0x78这四个字节开头,它就是条件ACE,这四个字节叫做ACE_CONDITION_SIGNATURE,是条件ACE的标志,其后面紧跟条件语句的编码。
ApplicationData字段的条件语句可以是一个条件表达式或由逻辑运算符连接的多个条件表达式,而每个条件表达式由关系运算符或逻辑运算符与所引用的安全属性组合,最终的值可以是TRUE、FALSE或UNKNOWN。
条件表达式引用经过安全认证的安全主体或资源的安全属性。经过认证的安全主体包括用户主体(User Principles)和设备主体(Device Principles),与它们相关的安全属性分别叫做用户要求(User Claims)和设备要求(Device Claims)(这个比较难翻译),并以一个个CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1结构实例的形式存在于这些安全实体的令牌中,分别组成UserClaims[]和DeviceClaims[]数组。
与资源相关的安全属性被称作资源属性(Resource Attributes),也是以CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1结构实例的形式存在,但该实例是存在于资源安全描述符的SACL的SYSTEM_RESOURCE_ATTRIBUTE_ACE中。这就是上篇提到的普通ACE后面resource_attribute字段所引用的部分。
下面的草图简单描述了条件表达式中引用的安全属性的概念。
条件ACE的应用逻辑:
条件语句的值 |
应用逻辑 |
FALSE |
所在的ACE在本次访问检查中不起作用 |
TRUE |
所在的ACE在本次访问检查中起作用 如果该ACE是访问允许ACE(ACCESS_ALLOWED_CALLBACK_ACE或ACCESS_ALLOWED_CALLBACK_OBJECT_ACE),那么该ACE中包含的权限会授予访问者; 如果该ACE是访问拒绝ACE(ACCESS_DENIED_CALLBACK_ACE或ACCESS_DENIED_CALLBACK_OBJECT_ACE),那么该条件ACE包含的权限就被拒绝授予访问者 |
UNKNOWN |
如果该条件ACE是ACCESS_ALLOWED_CALLBACK_ACE或ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,那么其中包含的权限就不会授予访问者(至少不是由该ACE授予); 如果该条件ACE是ACCESS_DENIED_CALLBACK_ACE或ACCESS_DENIED_CALLBACK_OBJECT_ACE,那么其中包含的权限会拒绝授予访问者。 |
条件ACE的存储格式
条件表达式中的操作符和操作数都是以“后缀表示法(Postfix notation)”存储在ApplicationData字段中。条件表达式具体体现为一系列占用连续存储空间的标记,每个标记的第一字节是一个标识该标记类型的类型码,每种标记类型都规定了其后内容的存储格式。条件表达式中共有三种标记:
- 运算符。只需一个字节的类型码,该类型码就是相应的逻辑或关系运算符。
- 文本。含有多种类型码,每种类型码都代表一种内置的数据类型以及其存储格式。文本可以是单值的,也可以是多值的,多值文本以复合类型存储(见后面文本标记表)。
- 属性名。一个类型码,代表带@前缀属性名的类型。
下面各表列出了用于条件表达式的各种标记以及每种标记的语法规定,其中的多字节整数、Unicode字符,都是以低位在先的方式存储。
条件表达式位于条件ACE的尾部,由于ACE的尾部要求以DWORD边界对齐,所以为达到这一要求有可能在尾部填充字节,用于填充的字节的值必须是0x00。
1.文本标记
类型码 |
文本数据类型 |
说明 |
0x00 |
无效标记 |
用于填充 |
0x01 |
8位符号整数 |
一个QWORD值,以补码形式存放8位符号整数(-128——+127) 然后是一BYTE类型符号值,最后是一BYTE类型的基数值。 |
0x02 |
16位符号整数 |
一个QWORD值,以补码形式存放16位符号整数(-32769——+32767) 然后是一BYTE类型符号值,最后是一BYTE类型的基数值。 |
0x03 |
32位符号整数 |
一个QWORD值,以补码形式存放32位符号整数 然后是一BYTE类型符号值,最后是一BYTE类型的基数值。 |
0x04 |
64位符号整数 |
一个QWORD值,以补码形式存放64位符号整数 然后是一BYTE类型符号值,最后是一BYTE类型的基数值。 |
0x10 |
Unicode字符串 |
首先是一个DWORD值,存储以字节数统计的字符串长度,然后是一些列的WORD值用于存放Unicode字符,低位字节在前 |
0x18 |
8位字节串 |
一个DWORD值存放以字节统计的串长度,随后是以BYTE存储的数据 |
0x51 |
SID |
一个DWORD值存放以字节统计的SID长度,随后是二进制格式的SID |
0x50 |
复合数据 |
一个DWORD值存放以字节统计的数据长度,随后是数据部分,可以是以上不同类型的数据以各自的格式存储。 |
上表中的整数类型格式用到的基数和符号代码必须从下表中取值:
基数 |
代码 |
说明 |