Выдача себя за пользователя в неправильном домене не вызывает исключения - PullRequest
5 голосов
/ 07 июня 2010

Я использовал общий код олицетворения, и он работал нормально, пока я не вставил случайный '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);

1 Ответ

4 голосов
/ 08 июня 2010

Я полагаю, что ответ заключается в том, как выполняется аутентификация. LogonUser попытается войти на локальный компьютер, на котором он был выполнен. Если этот компьютер находится в домене, ваш пароль будет проверен на контроллере AD и проверен.

Однако, если вы предоставите домен, он не сможет найти его для своей локальной базы пользователей в качестве запасного варианта. Локально он будет использовать NTLM (NTLM используется, когда клиент и сервер находятся на одной машине). NTLM проверяет хэши паролей и имя пользователя и, похоже, не беспокоит доменное имя ( ref doc ).

Если вместо этого вы используете формат UPN и установите для домена значение null , вы получите сообщение об ошибке, если домен не существует, и получите желаемый результат.

Это похоже на то, как если бы я создал пользователя A с паролем B на двух машинах, тогда эти пользователи могут получать доступ к машинам друг друга с локальными правами без необходимости входа в систему.

И все это является хорошей причиной, по которой вам следует держаться подальше от локальных учетных записей в доменном мире (по крайней мере, с теми же именами пользователей, префиксировать их) и почему машины, не входящие в домен, не должны видеть друг друга на сеть. И почему вы должны использовать Kerberos повсюду, если можете вместо NTLM.

...