在DCOM调用中使用默认身份验证和分离的伪装/冒充。

42

我试图使用DCOM(进程外)实现两个目标:

  1. 使用CoInitializeSecurity和其参数pAuthList来设置进程范围的身份验证。
  2. 使用伪装技术在特殊情况下(COM调用)更改调用者的身份。

我的想法:

  1. 据我所知,auth info结构包含所有新的COM调用的默认身份验证信息(例如RPC_C_AUTHN_WINNT的用户名和密码)。因此,COM应该使用auth结构中的信息而不是进程令牌。

  2. 通常,可以使用CoSetProxyBlanket为代理更改auth info。这对我有效。我的问题是:如果我自己模拟令牌并调用COM函数,它是否必须或不必须工作。我在各种MSDN文章中读到,将EOAC_DYNAMIC_CLOAKING应用于CoInitializeSecurity应该使其工作。但是,我的手动“伪装的COM调用”始终在服务器端显示进程标识。

客户端代码如下(使用Delphi):

var
authList : SOLE_AUTHENTICATION_LIST;
authidentity : SEC_WINNT_AUTH_IDENTITY_W;
authInfo : array[0..1] of SOLE_AUTHENTICATION_INFO;

pcAuthSvc : DWORD;
asAuthSvc : array[0..0] of SOLE_AUTHENTICATION_SERVICE;
Token : TJwSecurityToken;

begin
ZeroMemory( @authidentity, sizeof(authidentity) );

authidentity.User := 'Testbenutzer';
authidentity.UserLength := Length('Testbenutzer');
authidentity.Domain := '';
authidentity.DomainLength := 0;
authidentity.Password := 'test';
authidentity.PasswordLength := 4;
authidentity.Flags := SEC_WINNT_AUTH_IDENTITY_UNICODE;


ZeroMemory( @authInfo, sizeof( authInfo ) );

// NTLM Settings
authInfo[0].dwAuthnSvc := RPC_C_AUTHN_WINNT;
authInfo[0].dwAuthzSvc := RPC_C_AUTHZ_NONE;
authInfo[0].pAuthInfo := @authidentity;



authList.cAuthInfo := 1;
authList.aAuthInfo := @authInfo;

OleCheck(CoInitializeSecurity(
  NULL,                            // Security descriptor
  -1,                              // Count of entries in asAuthSvc
  NULL,                            // asAuthSvc array
  NULL,                            // Reserved for future use
  RPC_C_AUTHN_LEVEL_CONNECT,       // Authentication level
  RPC_C_IMP_LEVEL_IMPERSONATE,     // Impersonation level
  @authList,                       // Authentication Information
  DWORd(EOAC_DYNAMIC_CLOAKING),                       // Additional capabilities
  NULL                             // Reserved
  ));
//create COM object
int := CoSecurityTestObj.Create;
int.TestCall;
服务器还设置了EOAC_DYNAMIC_CLOAKING标志。它使用CoImpersonateClient获取线程令牌和用户名。它还使用CoQueryClientBlanket来获取authInfo(作为SEC_WINNT_AUTH_IDENTITY_W结构)。但是,这两个调用总是返回客户端的进程身份。此外,手动模拟也不起作用(2.)。
Token := TJwSecurityToken.CreateLogonUser(authidentity.User, '', authidentity.Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT);
 Token.ImpersonateLoggedOnUser;
 int := CoSecurityTestObj.Create;
 int.TestCall;

以下是需要翻译的内容:

再次提出问题:

  1. 我错了吗?为什么默认的身份验证信息结构(带有用户名和密码的WinNT)不在每个COM连接/调用中使用?

  2. 我错了吗?为什么手动模拟不起作用?请注意,我单独测试了第2个问题,因此第1个问题不能干扰。

这是JEDI Windows安全代码库的基础工作,我扩展以支持COM安全性。所以您的帮助将会遵循GPL/MPL。

参考文献:

伪装技术:

  1. http://msdn.microsoft.com/en-us/library/ms683778%28VS.85%29.aspx
  2. http://msdn.microsoft.com/en-us/library/cc246058%28PROT.10%29.aspx
  3. http://alt.pluralsight.com/wiki/default.aspx/Keith.GuideBook/WhatIsCoInitializeSecurity.html

CoInitializeSecurity和pAuthInfo

  1. http://www.codeguru.cn/vc&mfc/apracticalguideusingvisualcandatl/93.htm

获取安全性模板(服务器端)

  1. http://www.codeguru.cn/vc&mfc/apracticalguideusingvisualcandatl/92.htm

2
已解决问题 #2。常量 EOAC_DYNAMIC_CLOAKING 定义错误。我太蠢了 - ChristianWimmer
在情况1中,它应该使用当前标识,但仅当它能够委派它时,这只在Kerberos即域环境中才可能。此外,进程标识必须是“可信任的委派”。如果存在远程客户端并且您正在尝试调用另一个服务器(2个跳跃),传统的NTLM身份验证将不允许这样做。 - Ben
您是否曾经解决过CoInitializeSecurity在客户端进程范围内生效的问题? - misterti
1个回答

1

你尝试过使用RPC_C_AUTHN_LEVEL_CALL而不是RPC_C_AUTHN_LEVEL_CONNECT调用CoInitializeSecurity()吗?

通常在创建DCOM客户端时,我会创建COSERVERINFO并将其传递给带有安全凭据的CoCreateInstanceEx(),并记得在所有接口上调用CoSetProxyBlanket()。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接