Using SecureString with LogonUser

For training purposes, I am writing my own Active Directory client. To execute commands such as unlocking accounts and resetting passwords, I have to enter my administrator account and password and use WindowsIdentity.Impersonate to run the code as the administrator account. I wonder about my options for protecting my password, as it must be used many times in my program.

From what I understand, I can use SecureString to store the password. But to run the code as an administrator, I use WindowsIdentity.Impersonate , and to use this I have to get a token from LogonUser , which requires a regular string , not SecureString .

Therefore I need:

  • Login at startup

  • Convert Input to SecureString

  • Clear input

Then later, when I want to create a function that needs to be promoted:

  • Convert previously created SecureString to string

  • Pass the converted string to LogonUser

  • Clear conversion string to null

  • Run command

  • Clear LogonUser

Is this right? It seems strange that you need to convert SecureString to string in order to use it ... it looks like it will defeat the target and leave the password more vulnerable while I convert it.

EDIT: Fixed name for LogonUser

+6
source share
1 answer

In your UserImpersonation class UserImpersonation change the way LogonUser declared to use IntPtr instead of string for the password.

The sample code for Marshal.SecureStringToGlobalAllocUnicode has exactly what you need. Here is the relevant snippet:

 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern bool LogonUser(String username, String domain, IntPtr password, int logonType, int logonProvider, ref IntPtr token); ... IntPtr tokenHandle = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; try { // Marshal the SecureString to unmanaged memory. passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password); returnValue = LogonUser(userName, domainName, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle); } finally { // Zero-out and free the unmanaged string reference. Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); // Close the token handle. CloseHandle(tokenHandle); } 
+5
source

Source: https://habr.com/ru/post/980732/


All Articles