Share via


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.com

  • Anonymous
    March 06, 2006
    The comment has been removed

  • Anonymous
    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 code

  • Anonymous
    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