Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Impersonating a user in wrong domain doesn't throw exception

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);
like image 668
Rita Avatar asked Oct 15 '22 04:10

Rita


1 Answers

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.

like image 117
Mikael Svenson Avatar answered Oct 19 '22 01:10

Mikael Svenson