The right use of <identity impersonate="true"/> - c#

In my Website, Users who has logged in are able to change their profile pictures, and this process includes saving the uploaded image to a folder in the website's root directory.
When I tested it, I received an Error that I should grant access to this specific folder using permissions.
I do not have control over the Control Panel, the one who does said that he did grant the Images folder a READ and WRITE permissions to Others.
After Testing it again, once again the same error, so I edited web.config and included:
<identity impersonate="true"/>
And now everything seems to work perfectly. BUT, what did I just do here? Is there any security risk? Did I grant anonymous access to my website for everyone?

BUT, what did I just do here?
You are now running your website under the identity of the client user.
Is there any security risk?
That would depend on the permissions that this account has on the server. Usually it is bad practice to run a website with accounts that have lots of privileges. Ideally you should configure your website to run under an account that you explicitly grant privileges to the required folders.
The problem with your approach is that if another user that doesn't have access to the specified folder visits your website, it won't work for him. If on the other hand this is expected behavior then you are probably fine by impersonating user identities.
Did I grant anonymous access to my website for everyone?
No, this has nothing to do with authentication.

What you have done is given user rights to work under logged in user.
And there is a security risk for making impersonate true.
If you are on production, I would recommend you to read this article
http://support.microsoft.com/default.aspx?scid=kb;en-us;329290
"Using impersonation in the web.config allows you to override whatever identity was configured for the Application Pool the app is running under - it's just a more fine grained method to control identity ( on the app level vs. the ApplicationPool level), so you could have two apps run on the same AppPool, but one of them uses impersonation to use another identity."
courtesy: App pool identity versus impersonation identity?

Related

Accessing Active Directory Records Via ASP.NET

Seems like my local machine does not have the required permissions to write data into the Active Directory. I can read data but can not change and update it. Upon calling the .save() command I receive the next message: "Access is denied".
I do not use any login details in order to log into the Active Directory and I wish not to use any as well. I know it has something to do with the application pools and IIS generally, but I can't seem to find a working solution other than trying and changing some minor options and features.
EDIT:
This is the code I'm trying to execute:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "DOMAINANME"))
{
GroupPrincipal group = new GroupPrincipal.FindByIdentity(pc, "GROUPNAME");
group.Members.Remove(pc, IdentityType.SamAccountName, "USERNAME");
group.Save();
}
Your intuition is correct - you need proper permissions on the application pool account.
A simplest way would be:
Create a new domain user account
Add it to "Domain admins" group
In your iis server, locate the pool your application uses and change the pool identity to the newly created user
This way all requests from users to iis are run in the context of the domain admin and thus all requests from iis to AD will succeed - domain admins can operate the AD.
Although the above solution would work, it is probably not recommended. This is because the application does many things other than just connecting to the AD and if there are places that can be misused, you risk running unwanted requests in the domain admin context.
Usually then, such application would have two layers, a front layer and a back layer. The front layer runs in a restricted context and is responsible for all user requests. This is your application. A back layer is another web application that is not accessible from internet, only from the local intranet. This application runs in the domain admin context and serves as the gateway to the AD. The front application uses the back application to talk to the AD.
In order to execute code that needs specific permissions to your Active Directory, follow these steps:
Require the user to log into the ASP.NET application.
Have your code impersonate the currently-logged in user when executing the the Active Directory portion that needs that access.
There may be slight variations depending on the version of ASP.NET you are using, but basically...
Step 1
For the user login, just use the standard ASP.NET authentication configuration. Because it's the easiest to configure (and just works with AD) I'll document Windows Authentication here. This will prompt the user with a standard Windows login dialog box - where they will need to enter their domain credentials. To configure the application, make the following changes to the Web.config
<configuration>
...
<system.web>
...
<authentication mode="Windows" />
...
</system.web>
...
</configuration>
By default, ASP.NET should already know how to talk to the Active Directory when configured for Windows Authentication, so nothing else should be required, but if you find you need a separate Role Provider, feel free to take the one we use. (We also have instructions.) But again, you shouldn't need it.
Edit: You also need to make sure IIS is configured - using inetmgr.exe - to not allow anonymous access for the application. Otherwise, it will never prompt the user to log in. We typically disable Anonymous access and enable Windows and Basic authentication - because we need to support browsers that don't support NTLM.
Step 2
Now that you have an authenticated user, you can programmatically impersonate them. The following is adapted from Impersonating the authenticating user in code:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
try
{
// Do your writing to the AD here
}
finally
{
impersonationContext.Undo();
}
I also just discovered (while searching for reference links for this answer) that this is all pretty well documented in the MSDN article How To: Use Windows Authentication in ASP.NET 2.0
Let us know how it goes :-)

Access denied impersonating current user accessing network folder

Trying to list the directories and files within a specific folder. This folder will depend on the current user (Page.User) which logs in by Windows Authentication (NTLM) and is retrieved from the Active Directory (homedirectory property).
I am using a domain user to access the AD and retrieve the folder location, this works fine.
What fails is retrieving the sub folders using System.IO.DirectoryInfo.GetDirectories() even with impersonation.
Here's the code I'm using for impersonation:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
I have checked that the user being impersonated has access to the folder.
From what I have found so far it seems that I either need to set up delegation or Kerberos authentication, is this true? Are these the only ways to achieve this? Shouldn't impersonation be enough?
Impersonation allows the website service account to impersonate (pretend to be) another user on that machine. So querying AD to see what rights you (or the impersonated user) have is allowed.
Requesting access to a UNC share on another machine is asking the other machine to accept that the website service account is acting on behalf of the user being impersonated. This is delegating. The other machine is not checking the users credentials itself but delegating that check to the webserver.
If the client is connecting the the website from yet another machine (normally the case for webservers), then you have a "double hop" from client to webserver to UNC file server.
I'd suggest you need to configure Kerberos (via the SetSPN utility) and look enabling delegation rights for the website service account (witihin AD users and Computers). if you have problems setting this up, I heartily recommend a tool called DeleConfig.

Web Service Confusion - IIS - How to get web site's current directory and permissions issues

I have a few newbie web service/Windows rights questions since I've typically been a LINUX/embedded dev in the past.
What directories does a web service executing on a server have access to by default?
I ask because I tried to write to C:\ and got an access violation. I kind of assumed I would in this case, but I assume there are some areas of the file system the web service can write to and read from by default, right? Or is it just the current working directory?
*How can I give a web service permissions to look at a new directory it didn't have default access to?*
This is C# - ASMX - .NET 3.5 - IIS
The WebService doesn't really have any associated access controls associated with it (in a sense). It is however tied to the access control of the user account which is being used to run the application. By default this is usually some built in user account with limited permissions.
IIS uses a number of built-in Windows accounts, as well as accounts
that are specific to IIS. For security reasons, you should be aware of
the different accounts and their default user privileges. It can be a
security risk to change the identity of a worker process so that it
runs as an account with a high level of access, such as the
LocalSystem user account.
See a list of possible user accounts here: http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/3648346f-e4f5-474b-86c7-5a86e85fa1ff.mspx?mfr=true
If you have Anonymous Authentication enabled you can usually check the settings on that to see which account is being used to run the web service. (Depending on which version of IIS you are using, clicking Edit should let you view the default user account)
After finding the account, usually you will have to explicitly grant it the permissions on the folders (read and write) that you want to give it access to. The default user account usually has pretty limited access (and for good reason). You can grant permissions on the Security tab of the properties of any of the folders on a Windows file system (Properties->Security)
If you're using Windows Authentication, then you should have the same access rights as the authenticated user using the application as long as the resources are local to the IIS server.

C# 3.5 ASP.net File IO issue, UnauthorizedAccessException to file on network share

I get an UnauthorizedAccessException everytime I try to access (just read) a file on a network share "\\server\folder1\folder2\file.pdf."
I am impersonating the domain\aspnet user which has read & write access to the above mentioned folders. The file is not read-only.
I tried finding the permissions via System.Security.Permissions.FileIOPermission. It just says NoAccess to all files.
I'm not sure what else I can do.
I am using Visual Studio 2008, ASP.net 2.0 on Framework 3.5, WinXP, IIS 5.1.
ASP.NET user will not work with network path. So you need to have a windows account that
will have all the rights and then you need to imposernate things in web.config like following.
<identity impersonate="true" userName="domainname\windowuseraccount" password="password"/>
I'll assume you have set up the impersonation properly. You have turned off anonymous access, set the authentication mode to Windows and set impersonation to true, etc.
Even with all that done properly and the correct account impersonating you will still not be able to access the file. The account being impersonated is using what are called network credentials. These are only valid on the machine on which the impersonation is taking place. When you attempt to access a file on the computer itself the access is performed with the user's credentials but for a file on a share the access is done as a non-authenticated user and so no access is allowed.
In order to allow you to use the user's credentials for remote work, i.e. accessing a share, integrated security for a remote database, etc. you need to use delegation rather than impersonation. This is a somewhat complicated topic involving your Active Directory set-up and your IIS configuration. Have a look at this article, it should give you a good place to start.
Make sure that the domain user has Security rights and Share rights. That is, on the shared folder, add the domain user under the "Sharing" tab in the properties, as wells as under the "Security" tab.
What IIS version are you using? If it is version 6, you can place the web app in it's own application pool, then set the identity of that application pool to be a domain user account. Then, grant that domain user account access to the network share.
FYI you can place the following in an aspx file to verify what identify your pages are running as:
<%# Page Language="C#" %>
<% Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name); %>
To access a network share the above user will need to be a domain account setup by a network administrator.

Path.GetTempFileName -- Directory name is invalid

Running into a problem where on certain servers we get an error that the directory name is invalid when using Path.GetTempFileName. Further investigation shows that it is trying to write a file to c:\Documents and Setting\computername\aspnet\local settings\temp (found by using Path.GetTempPath). This folder exists so I'm assuming this must be a permissions issue with respect to the asp.net account.
I've been told by some that Path.GetTempFileName should be pointing to C:\Windows\Microsoft.NET\Framework\v2.0.50727\temporaryasp.net files.
I've also been told that this problem may be due to the order in which IIS and .NET where installed on the server. I've done the typical 'aspnet_regiis -i' and checked security on the folders etc. At this point I'm stuck.
Can anyone shed some light on this?
**Update:**Turns out that providing 'IUSR_ComputerName' access to the folder does the trick. Is that the correct procedure? I don't seem to recall doing that in the past, and obviously, want to follow best practices to maintain security. This is, after all, part of a file upload process.
This is probably a combination of impersonation and a mismatch of different authentication methods occurring.
There are many pieces; I'll try to go over them one by one.
Impersonation is a technique to "temporarily" switch the user account under which a thread is running. Essentially, the thread briefly gains the same rights and access -- no more, no less -- as the account that is being impersonated. As soon as the thread is done creating the web page, it "reverts" back to the original account and gets ready for the next call. This technique is used to access resources that only the user logged into your web site has access to. Hold onto the concept for a minute.
Now, by default ASP.NET runs a web site under a local account called ASPNET. Again, by default, only the ASPNET account and members of the Administrators group can write to that folder. Your temporary folder is under that account's purview. This is the second piece of the puzzle.
Impersonation doesn't happen on its own. It needs to be turn on intentionally in your web.config.
<identity impersonate="true" />
If the setting is missing or set to false, your code will execute pure and simply under the ASPNET account mentioned above. Given your error message, I'm positive that you have impersonation=true. There is nothing wrong with that! Impersonation has advantages and disadvantages that go beyond this discussion.
There is one question left: when you use impersonation, which account gets impersonated?
Unless you specify the account in the web.config (full syntax of the identity element here), the account impersonated is the one that the IIS handed over to ASP.NET. And that depends on how the user has authenticated (or not) into the site. That is your third and final piece.
The IUSR_ComputerName account is a low-rights account created by IIS. By default, this account is the account under which a web call runs if the user could not be authenticated. That is, the user comes in as an "anonymous".
In summary, this is what is happening to you:
Your user is trying to access the web site, and IIS could not authenticate the person for some reason. Because Anonymous access is ON, (or you would not see IUSRComputerName accessing the temp folder), IIS allows the user in anyway, but as a generic user. Your ASP.NET code runs and impersonates this generic IUSR___ComputerName "guest" account; only now the code doesn't have access to the things that the ASPNET account had access to, including its own temporary folder.
Granting IUSR_ComputerName WRITE access to the folder makes your symptoms go away.
But that just the symptoms. You need to review why is the person coming as "Anonymous/Guest"?
There are two likely scenarios:
a) You intended to use IIS for authentication, but the authentication settings in IIS for some of your servers are wrong.
In that case, you need to disable Anonymous access on those servers so that the usual authentication mechanisms take place. Note that you might still need to grant to your users access to that temporary folder, or use another folder instead, one to which your users already have access.
I have worked with this scenario many times, and quite frankly it gives you less headaches to forgo the Temp folder; create a dedicated folder in the server, set the proper permissions, and set its location in web.config.
b) You didn't want to authenticate people anyway, or you wanted to use ASP.NET Forms Authentication (which uses IIS's Anonymous access to bypass checks in IIS and lets ASP.NET handle the authentication directly)
This case is a bit more complicated.
You should go to IIS and disable all forms of authentication other than "Anonymous Access". Note that you can't do that in the developer's box, because the debugger needs Integrated Authentication to be enabled. So your debugging box will behave a bit different than the real server; just be aware of that.
Then, you need to decide whether you should turn impersonation OFF, or conversely, to specify the account to impersonate in the web.config. Do the first if your web server doesn't need outside resources (like a database). Do the latter if your web site does need to run under an account that has access to a database (or some other outside resource).
You have two more alternatives to specify the account to impersonate. One, you could go to IIS and change the "anonymous" account to be one with access to the resource instead of the one IIS manages for you. The second alternative is to stash the account and password encrypted in the registry. That step is a bit complicated and also goes beyond the scope of this discussion.
Good luck!
I encountered this error while diagnosing a console app that was writing in temp files. In one of my test iterations I purged all the files/directories in temp for a 'clean-slate' run. I resolved this self inflicted issue by logging out and back in again.
Could be because IIS_WPG does not have access to a temp folder. If you think it is a permission issue, run a Procmon on asp.net worker process and check for AccessDenied errors.
I was having the same problem with one of my ASP.Net applications. I was getting Path.GetTempPath() but it was throwing an exception of:
"Could not write to file "C:\Windows\Temp\somefilename", exception: Access to the path "C:\Windows\Temp\somefilename" is denied."
I tried a few suggestions on this page, but nothing helped.
In the end, I went onto the web server (IIS server) and changed permissions on the server's "C:\Windows\Temp" directory to give the "Everyone" user full read-write permissions.
And then, finally, the exception went away, and my users could download files from the application. Phew!
You can use Path.GetTempPath() to find out which directory to which it's trying to write.

Categories