Impersonation and Exception Filters in v2.0
A while back, I wrote about a potential security hole when malicious code can set up an exception filter before calling your code which does impersonation.
In the final release of v2.0, we've added a feature to help mitigate this problem. The CLR records that you've begun impersonation on the stack frame where you make the call to Impersonate(). If an exception is thrown, when the CLR walks the call stack looking for handlers, it will see this note and revert the impersonation when it moves past the frame.
This means that the following sample from my previous post would just work under v2.0:
public void SomeApi()
{
// Call LogonUser to get a token for the user
IntPtr userHandle = IntPtr.Zero();
bool loggedOn = LogonUser(
user,
domain,
password,
LogonType.Interactive,
LogonProvider.Default,
out userHandle);
if(!loggedOn)
throw new Win32Exception(Marshal.GetLastWin32Error());
// Begin impersonating the user
WindowsImpersonationContext impersonationContext = null;
try
{
WindowsIdentity.Impersonate(userHandle.Token);
DoSomeWorkWhileImpersonating();
}
finally
{
// Clean up
CloseHandle(userHandle);
if(impersonationContext != null)
impersonationContext.Undo();
}
}
When the call to Impersonate() is made, the CLR notes that on SomeApi()'s stack frame and if DoSomeWorkWhileImpersonating() happens to throw, the impersonation is reverted before any callers of the SomeApi() have their exception filters run.
Note that since this state is tied to the stack frame, you won't get this benefit if you impersonate in one method and revert in another:
public void SomeOtherApi()
{
// Begin impersonating the user
WindowsImpersonationContext impersonationContext = null;
try
{
impersonationContext = BeginImpersonating();
DoSomeWorkWhileImpersonating();
}
finally
{
// Clean up
if(impersonationContext != null)
impersonationContext.Undo();
}
}
Here, the impersonation is done in the BeginImpersonating() method, but is reverted in SomeOtherApi(). In this case, the stack frame for BeginImpersonating() is gone if DoSomeWorkWhileImpersonating() throws an exception. Since the BeginImpersonating() stack frame is the one which contained the annotation that impersonation needed to be undone, you lose the automatic revert behavior.
Obviously getting the undo for free is a much better option than having to go through all the work of protecting your code manually, so as you begin upgrading your code to run with v2.0 of the framework, you might want to look for places where you don't both impersonate and undo the impersonation in the same method.
Comments
Anonymous
March 03, 2006
Hi Shawn,excellent! good work!now i have to change my slides again :))Anonymous
March 03, 2006
Trackback from dotnetkicks.comAnonymous
March 06, 2006
The comment has been removedAnonymous
March 31, 2006
Web Resources
[.NET Framework] GotDotNet CodeGallery
Share, find, download and discuss evolving...Anonymous
May 05, 2006
The following links to .NET resources have been collated over time with the assistance of colleagues. ...Anonymous
December 06, 2006
WWWTC #9 ranks 10 out of 10 on the "difficult and subtle" scale. Let's say we write the following...Anonymous
December 06, 2006
WWWTC #9 ranks 10 out of 10 on the "difficult and subtle" scale. Let's say we write the following codeAnonymous
February 24, 2009
.NET doesn't care what language you write in - as long as your code compiles to MSIL, it's a .NET application