SDK 文档不一致:支持的 Kerberos Token 声明类型





5.00/5 (1投票)
从用户令牌检索声明信息时,SDK 中关于支持的数据类型的文档是错误的。
引言
在过去几周里,我一直在编写一个开源的 whoami 版本。在显示用户令牌声明的部分,我使用 GetTokenInformation
从用户令牌中检索该信息。用户或设备的声明可以有不同的 datatype
,这取决于属性的类型。然而,测试所有支持的 datatype
被证明是不可能的。
我在此记录此事,以防有人遇到同样的问题,这样他们就不必花一天时间来追踪问题。
数据类型文档
GetTokenInformation
的文档规定,以下 datatype
支持声明:
值 | 含义 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 0x0001 | Values 成员指向一个 LONG64 值数组。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 0x0002 | Values 成员指向一个 ULONG64 值数组。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING 0x0003 | Values 成员指向一个指向 Unicode 字符串值的指针数组。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN 0x0004 | Values 成员指向一个 CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE 值数组。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_SID 0x0005 | Values 成员指向一个 CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE 值数组,其中每个 CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE 的 pValue 成员是一个 PSID 。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN 0x0006 | Values 成员指向一个 ULONG64 值数组,其中每个元素表示一个布尔值。值 1 表示 TRUE ,值 0 表示 FALSE 。 |
CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING 0x0010 | Values 成员指向一个 CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE 值数组。 |
然而,无论我怎么做,即使修改了我沙箱中的 AD 架构,我也无法设置具有 CLAIM_SECURITY_ATTRIBUTE_TYPE_SID
或 CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING
datatype
的声明。我也没找到 CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN
,但那只是一个 string
,所以没关系。我之所以想设置这些声明类型,主要是因为我想看看 whoami 如何显示这些声明,以便我的输出格式与此相同。
文档不一致
经过大量搜索,我最终找到了相关的目录服务协议文档。该文档清楚地记录了目录服务方面的用户声明的 datatype
。
typedef struct _CLAIM_ENTRY {
CLAIM_ID Id;
CLAIM_TYPE Type;
[switch_is(Type), switch_type(CLAIM_TYPE)]
union {
[case(CLAIM_TYPE_INT64)]
struct {
[range(1, 10*1024*1024)] ULONG ValueCount;
[size_is(ValueCount)] LONG64* Int64Values;
};
[case(CLAIM_TYPE_UINT64)]
struct {
[range(1, 10*1024*1024)] ULONG ValueCount;
[size_is(ValueCount)] ULONG64* Uint64Values;
};
[case(CLAIM_TYPE_STRING)]
struct {
[range(1, 10*1024*1024)] ULONG ValueCount;
[size_is(ValueCount), string] LPWSTR* StringValues;
};
[case(CLAIM_TYPE_BOOLEAN)]
struct {
[range(1, 10*1024*1024)] ULONG ValueCount;
[size_is(ValueCount)] ULONG64* BooleanValues;
};
[default] ;
} Values;
} CLAIM_ENTRY,
*PCLAIM_ENTRY;
这确凿地证明了在目录服务方面,SID 和 Octet string 不是支持的声明类型。这也意味着 GetTokenInformation
的文档是错误的。
或者更确切地说,我怀疑定义 GetTokenInformation
接口的团队只是采用了支持的属性类型列表。从技术上讲,每个 AD 属性都可以用作声明类型,因此接口不必担心当前支持哪些声明类型,而是具有用于处理未来更改的 typedef
。
关于那些不支持的数据类型的思考
经过一番思考,我得出结论,那些不支持的 datatype
在用户声明的上下文中没有意义。
考虑 SID 属性。例如,如果您想将对象 A 链接到对象 B,您可以使用 SID 属性。可以想象,然后您可以定义一个声明类型来对该链接提出要求。例如,只有与给定 SID 链接的用户帐户的用户才能访问资源 R。再次,您也可以使用区分名称 (Distinguished Name) 来实现这一点。它还将具有用户可读且在对象 B 迁移时可转移的优点(因为 DN 可以重用,而 SID 不可以)。
我能看到的 Octet string 的潜在用例甚至更少。它基本上是一个二进制大对象。当然,您可以将很多东西放入 Octet string 中。哈希、加密信息、证书,随便什么。问题在于 Kerberos 如何对该信息做有意义的事情来做出授予访问权限的“是/否”决定。这将需要大量的额外复杂性,并且它本质上将是一种看起来非常像证书的东西,而证书已经得到了很好的支持。
我还没有找到设置 FQBN 声明的方法,但这问题不大,因为它本质上只是一个 string
,所以如果我们收到它,我们可以像处理其他 string
一样读取它。
结论
出于测试目的,目前无法对那些不支持的 datatype
做任何事情,所以您不必担心它们。我认为最好的做法是处理支持的 datatype
,并在其他类型标识符上触发错误。如果 Microsoft 最终支持它们,您至少会收到一个正确的错误消息。
历史
- 2022 年 10 月 7 日:第一版