Here I wrote about how important it is for extensibility code like providers or modules to be aware of the current security context when you want to access external resources.
You can streamline a lot of the code I showed by using the Impersonate method on the HostingEnvironment class. Impersonate does exactly the right thing:
- uses the process identity if client impersonation is enabled (or no impersonation at all)
- uses the application identity if application impersonation is enabled
A first (and naive) refactoring could be:
using (HostingEnvironment.Impersonate())
{
// access external resource
}
But be aware of the multi pass exception handling “feature” of the CLR. If a VB.NET caller could figure out how to cause an exception while you are impersonating (e.g. by disconnecting the network or passing in special parameters), the process identity can be leaked back to the caller if client impersonation is enabled. Technically – the catch block of the caller runs before the finally block of the library (and using is just syntactic sugar for a try/finally block).
Malicious code exploiting exception filtering could look like this:
Sub MaliciousCaller()
Try
Library.MethodThatUsesImpersonation()
Catch ex As Exception When leakContext() = True
End Try
End Sub
Function leakContext() As Boolean
Response.Output.Write(“Identity inside filter: {0} <br />”,
WindowsIdentity.GetCurrent().Name)
Return True
End Function
Now in .NET 2.0 RTM, the CLR incorporates a defense in depth measure for this special case. Shawn wrote about it here. But this won’t help when using HostingEnvironment, because, as Shawn describes, the impersonation has to happen on the same stack frame as the (potential) exception. To mitigate this, you have to wrap the using block in a try/catch block and handle the exception (e.g. re-throwing it).
The complete code looks like this:
try
{
using (HostingEnvironment.Impersonate())
{
// access external resource
}
}
catch
{
throw;
}