When You’re Not Yourself, Impersonate!
Don Kiely explores impersonation as it relates to ASP.NETsecurity.
October 30, 2009
Secure ASP.NET
When You re Not Yourself,Impersonate!
By Don Kiely
I recently completed courseware for AppDev that focuses on someadvanced features of the .NET Framework 2.0. Several of the course sections Iwrote deal with security; along the way I had to take a good look atimpersonation. Because impersonation is frequently the subject of questions onthe ASP.NET support forums at http://www.asp.net(of which I m a moderator), I thought this would be good fodder for a securitycolumn. I ve derived the material here from the AppDev course I wrote.
One of the most powerful things you can do with Windowsidentity objects in .NET is to impersonate another user for a short time. Whilethe impersonation is in effect, the code executes with the security context ofthe impersonated user instead of the currently logged-in user. If it creates afile, the impersonated user owns the file. If the logged-in user has access toa SQL Server database, but the impersonated user doesn t, any attempt toconnect to the database will throw a security exception.
By default, ASP.NET Web applications run under a specialWindows account: MACHINENETWORK SERVICES in Windows Server 2003 and later andMACHINEASPNET in earlier versions of Windows. You can set up an ASP.NETapplication to be able to impersonate the actual user and perform actions withthat user s security context.
Many of the examples of ASP.NET impersonation you find,particularly on MSDN, are quite complicated. This seems to have led many peopleto think that it is a complex operation. Although it is certainly an advancedtechnique, it isn t hard to do and the code is fairly simple. The sampleapplication I discuss here starts running as the default ASP.NET processidentity, then impersonates the current logged-in user. While impersonating theuser, it creates a text file in the impersonated user s My Documents directory.Then the code will revert to the ASP.NET process identity. Along the way, itprints messages to the Web page about which identity is currently in effect.Below are the contents of the page when the sample runs (RIVERCHASER is themachine, of course).
Impersonation Sample
Current identity: RIVERCHASERASPNET
Impersonating RIVERCHASERdonkiely
Current identity: RIVERCHASERASPNET
To make this work, you must do a little setup once you vecreated the ASP.NET project. First, create an IIS virtual directory that pointsto the directory containing the ASP.NET application. Impersonation won t workusing the Cassini Web server that Visual Studio normally runs when you debug aWeb site. The entire application runs with the logged in user s securitycredentials rather than that of either NETWORK SERVICES or ASPNET. This makessense, because IIS is not involved when you use Cassini.
Next, change the authentication method for the virtualdirectory to Integrated Windows authentication only. By default, new virtualdirectories use both Windows and anonymous access. In the directory s propertypage s Directory Security tab, click the Edit button in the Anonymous accessand authentication control section. Uncheck the anonymous option and leave theWindows Integrated authentication option checked.
Once you have the virtual directory set up, it s time tocode. Create an ASP.NET application. Here I m using VB, but you can easilytranslate it to C#. Put all the code in the page s Load event procedure. You llalso need to import the System.IO and System.Security.Principal namespaces.After writing a page title, the code uses the shared GetCurrent method of theWindowsIdentity class to print the name of the current user under which thecode is running. This will be the ASP.NET process identity:
Response.Output.Write("
Impersonation Sample
")
Response.Output.Write("
Current identity: {0}
",_
WindowsIdentity.GetCurrent.Name)
Next, the code gets a reference to the current Windowsprincipal. This is the user who is running the application, the impersonated user,switching the security context from the ASP.NET process account. The Page classin ASP.NET has a User property that returns an IPrincipal object directly soyou don t have to use .NET Framework classes. The code then uses the Identityproperty to get the associated WindowsIdentity object, casting the IIdentityobject returned from the Identity property to a WindowsIdentity object. It alsoinstantiates a WindowsImpersonationContext object that we ll use later torevert the impersonation:
Dim prin As IPrincipal = Me.User
Dim iden As WindowsIdentity = _
DirectCast(prin.Identity, WindowsIdentity)
Dim wic As WindowsImpersonationContext = Nothing
The code below calls the identity s Impersonate method,which kicks in the impersonation. It returns a WindowsImpersonationContextobject used later to undo the impersonation:
wic = iden.Impersonate
Now the code in the page is running with the impersonateduser s security context. It once again writes the user s name, which is nolonger the ASP.NET process context. While still impersonating the user, itcreates a text file in the user s My Documents directory:
Response.Output.Write("
Impersonating {0}
",_
WindowsIdentity.GetCurrent.Name)
Dim path As String = _
Environment.GetFolderPath( _
Environment.SpecialFolder.MyDocuments) & "text.txt"
File.WriteAllText(path, "Hello from " _
&WindowsIdentity.GetCurrent.Name)
In the Finally block the codecalls the WindowsImpersonationContext s sole custom method, Undo. This reverts the security context of the application to theASP.NET process account. It once again writes out the current user s name toprove that the security context is once again that of the ASP.NET processaccount:
Finally
wic.Undo()
End Try
Response.Output.Write("
Current identity: {0}
",_
WindowsIdentity.GetCurrent.Name)
For fun, go ahead and run the application in VisualStudio, which uses Cassini by default. You ll find that you as the logged inuser are displayed as both the current identity and the impersonated user. Whata concept, impersonating yourself! Then try it for real. Use your favorite Webbrowser it doesn t have to be Internet Explorer, as long as it is a recentversion of the browser and enter this URL:
http://localhost/appdev/default.aspx
You should see the page as shown above.
Now check the file that the page created whileimpersonating you. In Windows Explorer navigate to your My Documents directoryand look for the text.txt file. Open it in Notepad or another text editor tosee the content, which, when I ran it is:
Hello from RIVERCHASERdonkiely
But there s more to this than just some content. To provethat donkiely actually created and owns the file, open Windows Explorer. Right-click the file and select Properties from the pop-up menu.Select the Security tab and click the Advanced buttonin the lower right of the dialog box. This opens the Advanced Security Settingsdialog box. Select the Owner tab and see that the impersonated user owns thefile, rather than the ASP.NET process account (which wouldn t be able to writeto my My Documents directory, anyway).
Impersonation is a powerful technique! You won t want touse it often because it is fraught with potential security risk, allowing a Webapplication to do things on a server as a user that is presumably more powerfulthan the ASP.NET process account. But when you need it, it can add some nicecapabilities to your Web applications.
DonKiely, MVP, MCSD, is a senior technology consultant, building customapplications as well as providing business and technology consulting services.His development work involves tools such as SQL Server, Visual Basic, C#,ASP.NET, and Microsoft Office. He writes regularly for several trade journals,and trains developers in database and .NET technologies. You can reach Don at mailto:[email protected] and readhis blog at http://www.sqljunkies.com/weblog/donkiely/.
About the Author
You May Also Like