nsspi icon indicating copy to clipboard operation
nsspi copied to clipboard

Issues (reading registry and other stuff) after impersonation (using NTLM)

Open ggo98 opened this issue 7 years ago • 4 comments

Hello,

I have tried nsspi, and it's a very nice component. However I'm having issues after impersonation:

  • with special folders (MyDocuments)
  • trying to read registry.
  • The existing code which writes a file does not work either.

The server is running under a user profile (Someuser2) which:

  • is part of the Users group.
  • has the "Impersonate a Client AfterAuthentication" User Right (SeImpersonatePrivilege). I suppose the problem is with Someuser2. I hope you can point me to the right direction...

The client is running under another profile.

The tests are performed in the same workgroup (no domain), and the problem occurs when the client and the server run on the same machine (Win 8.1) or on 2 different machines (server=Win8.1,client=Win2016).

Some stuff works, but:

  • I have added serveral lines of code in ServerForm.impersonateButton_Click() to read the registry and it does not work (exceptions thrown).

  • The code which is is originally in ServerForm.impersonateButton_Click() to write a file does not work anymore either.

  • Of course I did not change anything else in the code.

      private void impersonateButton_Click(object sender, EventArgs e)
      {
      	ImpersonationHandle handle;
    
      	// Get the MyDocuments folder before impersonation: WORKS.
      	Console.WriteLine("MyDoc BEFORE impersonation=" + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
    
      	using (handle = this.serverContext.ImpersonateClient())
      	{
      		// Get the current UserName AFTER impersonation: WORKS.
      		Console.WriteLine("Starting impersonation: " + Environment.UserName + Environment.NewLine);
    
      		// Get the MyDocuments folder AFTER impersonation: *** DOES NOT WORK ***.
      		// (an empty string is returned)
      		string s = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
      		Console.WriteLine("MyDoc AFTER impersonation=" + s);
    
      		MessageBox.Show("Starting impersonation: " + Environment.UserName);
      		MessageBox.Show("MyDoc AFTER impersonation=" + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); // EMPTY
    
      		try
      		{
      			Console.WriteLine("GetVal");
    
      			// *** DOES NOT WORK (Exceptions) ***
      			// (Details about the exceptions below)
      			var data = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion",
      				"CommonFilesDir", "Not found");
    
      			Console.WriteLine(data.ToString());
      			int a = 123;
      		}
      		catch (Exception ex)
      		{
      			Console.WriteLine("EX: " + ex.ToString());
      			Console.WriteLine(ex.StackTrace);
      			ex = ex;
      			int a = 123;
      		}
    
      		try
      		{
      			// *** DOES NOT WORK (Exception) ***
      			// (Detail about the exceptions below)
      			FileStream stream = File.Create(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + @"\test.txt");
      			StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
    
      			writer.WriteLine("Hello world.");
    
      			writer.Close();
      			stream.Close();
      		}
      		catch (Exception ex)
      		{
      			Console.WriteLine("EX2: " + ex.ToString());
      			Console.WriteLine(ex.StackTrace);
      			ex = ex;
      			int a = 123;
      		}
      	}
    

` Here are the details I could get with the Visual Studio debugger:

System.ArgumentException occurred HResult=-2147024809 Message=Unknown error "1346". Source=mscorlib StackTrace: at System.Diagnostics.Tracing.EventProvider.Register(Guid providerGuid) InnerException:

(1346 is Either a required impersonation level was not provided, or the provided impersonation level is invalid.)

System.Security.SecurityException occurred HResult=-2146233078 Message=Requested registry access is not allowed. Source=mscorlib StackTrace: at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource) InnerException:

(-2146233078 = 0x8013150A = COR_E_SECURITY)

Here are the details in the console:

TestServer Server: Received ClientToken Server: Sent ServerToken Server: Received ClientToken Server: Sent ServerToken MyDoc BEFORE impersonation=C:\Users\Someuser2\Documents Starting impersonation: ggo

MyDoc AFTER impersonation= GetVal *** REGISTRY access *** EX: System.Security.SecurityException: Requested registry access is not allowed. at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource) at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable) at Microsoft.Win32.Registry.GetValue(String keyName, String valueName, Object defaultValue) at TestServer.ServerForm.impersonateButton_Click(Object sender, EventArgs e) The Zone of the assembly that failed was: MyComputer System.Security.SecurityException at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource) at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable) at Microsoft.Win32.Registry.GetValue(String keyName, String valueName, Object defaultValue) at TestServer.ServerForm.impersonateButton_Click(Object sender, EventArgs e)

*** File creation access *** EX2: System.IO.IOException: Unknown error "1346". at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, I nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions o ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolea n useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize) at System.IO.File.Create(String path) at TestServer.ServerForm.impersonateButton_Click(Object sender, EventArgs e) System.IO.IOException at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, I nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions o ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolea n useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize) at System.IO.File.Create(String path) at TestServer.ServerForm.impersonateButton_Click(Object sender, EventArgs e)

Thank you very much, best regards, Olivier gg.

ggo98 avatar Aug 15 '18 19:08 ggo98

I believe that you need 'Act as part of operating system' privilege too. Give this permission too and check it again.

zoltanharmath avatar Aug 15 '18 23:08 zoltanharmath

Thank you for the suggestion. Unfortunately it didn't help. I have even restarted the system just in case, but it's still not working. I have noticed that it works when I run the server example as SYSTEM, but I still can't figure out which permission is missing for Someuser2...

ggo98 avatar Aug 17 '18 21:08 ggo98

Is it working if the Someuser2 member of the 'Administrators' group?

Try to give the 'Create global objects' privileges too and try it again.

zoltanharmath avatar Aug 18 '18 13:08 zoltanharmath

It didn't work with the 'Create global objects' privilege, but adding Someuser2 to the 'Administrators' group did work! Thank you. I guess I have to figure out what are the user rights differences between the 'Administrators' group and the regular 'Users' group regarding impersonation... Thank again.

ggo98 avatar Aug 20 '18 07:08 ggo98