在错误的域中模拟用户不会引发异常

Rit*_*ita 5 .net c# impersonation identity

我使用了常见的模拟代码,它工作得很好,直到我在域中插入随机的'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());
    } 
Run Code Online (Sandbox Code Playgroud)

我在我的域上使用了一些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);
Run Code Online (Sandbox Code Playgroud)

Mik*_*son 4

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

然而,如果您提供一个域,它找不到它,它将针对它自己的本地用户库进行身份验证作为后备。本地它将使用NTLM(当客户端和服务器是同一台机器时使用NTLM)。NTLM 验证密码哈希值和用户名,并且似乎不关心域名(参考文档)。

如果您改用UPN 格式并将域设置为 null,那么如果域不存在,您将收到错误消息,并得到您想要的结果。

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

所有这些都是您应该远离域世界中的本地帐户(至少使用相同的用户名,前缀)以及为什么非域计算机不应该能够在网络上相互看到的一个很好的理由。如果可以的话,为什么应该全部使用 Kerberos 而不是 NTLM。