冒充错误域中的用户不会引发异常
我使用了常见的模拟代码,它工作得很好,直到我在域中插入随机“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);
I used the common impersonation code and it worked just fine, until I inserted random 'dggdgsdg' in domain - and it worked nonetheless...
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());
}
I used some TestUser on my domain, and it worked. I then switched domain, to random nonsense 'werwerhrg', and it impersonated the TestUser on my domain! Why? I would expect an exception to be thrown, why on earth is it working?
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我相信答案在于如何执行身份验证。
LogonUser
将尝试让您登录到执行该操作的本地计算机。如果此计算机位于域中,则将根据 AD 控制器检查您的密码并进行验证。但是,如果您提供一个域,它找不到它,它将针对其自己的本地用户库进行身份验证作为后备。本地它将使用NTLM(当客户端和服务器是同一台机器时使用NTLM)。 NTLM 验证密码哈希值和用户名,并且似乎不关心域名 (参考文档)。
如果您使用 UPN 格式并将域设置为 null 如果域名不存在,你会得到一个错误,并得到你想要的结果。
这类似于我在两台计算机上创建用户 A 和密码 B,然后这些用户可以使用本地权限访问彼此的计算机,而无需登录。
所有这些都是您应该远离域世界中的本地帐户(至少使用相同的用户名,前缀)以及为什么非域计算机不应该能够在网络上相互看到的一个很好的理由。如果可以的话,为什么应该全部使用 Kerberos 而不是 NTLM。
I believe the answer lies in how authentication is performed.
LogonUser
will attempt to log you on to the local computer it was executed on. If this computer is on a domain, then your password will be checked against an AD controller and be verified.If you however provide a domain it cannot find it will authenticate against it's own local userbase as a fallback. Locally it will use NTLM (NTLM is used when client and server are the same machine). NTLM verifies password hashes and the username, and seems to not bother with the domain name (ref doc).
If you use UPN format instead and set domain to null then you will get an error if the domain is non-existant, and get your wanted result.
This is similar as if I create a user A with password B on two machines, then those users can access each others machines with the local rights without having to log on.
And all this is a good reason why you should stay away from local accounts in a domain world (at least with the same usernames, prefix them), and why non-domain machines should not be able to see each other on a network. And why you should use Kerberos all over if you can instead of NTLM.