【问题标题】:Impersonating a user in wrong domain doesn't throw exception冒充错误域中的用户不会引发异常
【发布时间】:2011-02-28 20:41:34
【问题描述】:

我使用了通用的模拟代码,它工作得很好,直到我在域中插入了随机的“dggdgsdg”——但它仍然工作......

if (LogonUser(Username, Domain, Password, Logon32LogonInteractive, Logon32ProviderDefault, ref existingTokenHandle) &&
    DuplicateToken(existingTokenHandle, (int)SecurityImpersonationLevel.SecurityDelegation, ref duplicateTokenHandle))
    {
            Identity = new WindowsIdentity(duplicateTokenHandle);
            ImpersonationContext = Identity.Impersonate();
    }
    else
    {
            throw new Win32Exception(Marshal.GetLastWin32Error());
    } 

我在我的域上使用了一些 TestUser,它确实有效。然后我将域切换到随机的废话“werwerhrg”,它在我的域上冒充了TestUser!为什么?我希望会抛出一个异常,为什么它在工作?

private const int Logon32LogonInteractive = 2;
private const int Logon32ProviderDefault = 0;

public enum SecurityImpersonationLevel
        {
            SecurityAnonymous = 0,
            SecurityIdentification = 1,
            SecurityImpersonation = 2,
            SecurityDelegation = 3
        }
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool DuplicateToken(IntPtr existingTokenHandle, int securityImpersonationLevel, ref IntPtr duplicateTokenHandle);

【问题讨论】:

  • 通常使用域身份验证,我看到的是用户名/域组合在一起。因此,您指定 MyDomain\TestUser 或 TestUser@MyDomain。尝试像这样指定您的用户名,看看会发生什么。我猜你的机器是目标域的成员,并且它试图使用该域上的用户而不是指定的域。
  • @Tim,我试过了,没有运气。如果我指定 'domain\testUser' 作为用户名,我会得到一个异常 'unknown username or bad password'。
  • 发布您的 P/Invoke 声明。
  • 不是这样的。我怀疑这是一个功能,而不是一个错误。回退到默认域,类似的东西。 Serverfault.com 上的某个人会知道。
  • 你能在不是域成员的机器上测试你的代码吗?我有点同意 Hans 的看法,认为某种后备措施已经到位。

标签: c# .net identity impersonation


【解决方案1】:

我相信答案在于如何执行身份验证。 LogonUser 将尝试让您登录到执行它的本地计算机。如果这台计算机在域中,则将根据 AD 控制器检查您的密码并进行验证。

但是,如果您提供一个域,它无法找到它,它将针对它自己的本地用户群进行身份验证作为后备。在本地它将使用 NTLM(当客户端和服务器是同一台机器时使用 NTLM)。 NTLM 验证密码哈希和用户名,似乎不关心域名 (ref doc)。

如果你使用UPN format instead and set domain to null,那么如果域不存在,你会得到一个错误,并得到你想要的结果。

这类似于我在两台机器上创建一个密码为 B 的用户 A,然后这些用户可以使用本地权限访问彼此的机器,而无需登录。

所有这些都是为什么您应该远离域世界中的本地帐户(至少使用相同的用户名,为其添加前缀)以及为什么非域计算机应该能够在网络。以及为什么你应该在可能的情况下使用 Kerberos 而不是 NTLM。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多