I have a search algorithm that tries to resolve the location of a directory on a local drive. The directory obviously will need to access other directories present on the system if it is searching for a sub directory of one of those. However in doing this I keep getting the UnauthorizedAccessException.
I would like to provide the search mechanism the access privileges of the active user when it is run, how can I achieve this.
In most cases, the correct answer is that you shouldn't.
Your algorithm should catch the UnauthorizedAccessException, accept that it won't be allowed to navigate further down that folder, and act like the folder is empty.
That means that sometimes you will get an answer that a directory you are looking for doesn't exist when it technically does exist. That's OK. It's the way it's supposed to be. If you don't have permission to it, it doesn't exist for you.
Folders protected under some other users' rights are "private". A program that "Joe" runs is not supposed to look at the folders that belong to "Mary". That's the whole point of permissions.
There are very few controlled exceptions to the rule. Notoriously, Disk Backup and Anti-virus applications need to be able to navigate the entire disk, regardless of folder permissions. They do so by setting up a service that runs under a highly privileged account (maybe "SYSTEM", maybe something else). It will likely be an account that holds the SeBackupPrivilege.
You can do that for your program, if you really need to scan the whole disk, but for most application scenarios you really shouldn't. Only a machine-wide maintenance application like an anti-virus or backup program should be given that kind of authority.
It's not that it's "overkill"; it's that it's "wrong". It does not play by the rules.
Related
I am writing log for my application at a path saying :-
"C:\Folder1\Folder2\Myfile.txt" (Configurable)
if this file does not exist I am creating folder structure and file inside my code(If there is no C drive I pop up a message saying log directory doesnt exist).
In code review a colleague said that I should not create folder and files using code rather should ask the client to create the file and only perform write operation on this file.
He says there are security issues with this but not sure what, so I thought of posting it here.
Please help me deciding whether I should create file if not exist or ask the client to create on every installation.
What are the security implications with the first approach?
The write issues are that the user trying to create in the C root folder, may not have permissions to create it there. Never assume the user is an admin always.
Also this is the problem with windows' UAC which will be a problem.
Yes there could be issues. Your program will most likely run under the interative user account and therefore be subject to any UAC conditions imposed on it.
One approach, if this is just a log file, would be to use a temporary file, so use:
http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx
This should be created in a an area local to the logged on user that should allow writing of files.
The security issue i see is the ability of your web application to access and write the files inside the directory (configurable, as you mentioned).
To verify the the access by checking the permissions given to the account under which your apppool is running
or through code see this
No code is inherently unsafe. This all depends on how rest of your code looks like, but as a general rule of thumb you should limit which files your application can access and how it can access them. Limit this as much as possible, without damaging your applications functionality.
Security vulnerabilities which may come from this is allowing user to read file which he shouldn't read, or write to an important file and damage it that way. For example, if file path is being created using user input, user may modify the path so that he accesses file which is not allowed to access.
If you create a path like so:
string filePath = "c:\\mysafefolder\\" + fileName;
and user enters a relative path, for example ..\Windows\Passwords.txt he will effectively gain access to c:\windows\passwords.txt.
If you configure your application to block access to any part of file system except mysafefolder, this attempt to read a secret file will fail.
This is just an example of what might happen, and why it is a good idea to limit your application permissions. Your code might be perfectly safe at this point, but limiting permissions is thinking ahead.
My application basically creates an XML file in C:\ProgramData\MyAppFolder and dumps config settings in it.
I need to allow even standard users to have permission to add or delete settings to these config files. Right now I see that standard users only have read/execute permission but not "Full Control".
I've seen other questions being answered with ways to modify permissions to that particular folder but I don't want to change the default permission level, since it might be reset by a system admin.
If C:\ProgramData can't give that access to all users, is there any folder that best suits the needs of application?
EDIT:
My initial question might be misleading. I don't want to give rights to users, but rather allow the application to modify the XML file when it is run by all users.
DECISION:
I think changing the permissions while creating the folder in ProgramData is the only option.
And if that's not possible, CommonDocuments is the way to go.
Thanks Eve.
I would use a folder in the Environment.SpecialFolder enum.
Example:
var path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
Assuming you have an installer for your application, your installer can create a subfolder in the common appdata directory (aka C:\ProgramData) which your application will have read/write access to. Depending on your choice of installation technology you can set the permissions on that folder as well, although that may be overkill. I know with WiX basically all you have to do is a per-machine installation and make sure that sub folder gets created.
Users should not be allowed to write arbitrary data to this directory. This is equivalent to regular users being able to modify the C:\Users\AllUsers directory. If users need to be modifying this directory you have serious design flaws and should reconsider this approach. What should happen is the users are given GUI interface to interact with that manipulates these values behind the scenes without giving them direct access, similar to how getters/setters work in most programming languages. Needless to say it is a very large security hole when regular users can corrupt a system for other users.
UPDATE
I don't want to give users direct access to the file. My question
might have been misleading. I want to allow the program to have full
control on the file even when it being run by all users. I'm actually
doing this: "users are given GUI interface to interact with that
manipulates these values behind the scenes without giving them direct
access"
This article which has far too much information to post here, will provide details on remaining secure as to not leak permissions. The first thing you want to do is make sure that your application user is in its own group and cannot login/have any special permissions. What you can than do is have this group added to the directory with write permissions, which would allow this application to perform these tasks. If that is not possible you will need to work within UAC to not break the security of the system as is detailed in the article above.
Second Update
Thanks for the link. Any suggestions on some other folder which can do
the job, rather than messing with the permissions?
Sure you can write it into the directory where the application is written to, i.e. C:\Program Files\Some Awesome Program, this keeps everything in one place, and you only have to worry about your user/group and anything that the person who installed it has allowed for. It also prevents other people from messing with it unless of course they are administrators.
Is there a reliable method to check if an application is run from somewhere beneath program files?
If the user installs the application to program files on local machine, we need to put writable files somewhere else to avoid virtualization on Vista and Win7. When installed to a network disk, though, we want to keep these files with the installation for shared access among users.
Today we do an string comparison between startup path and CSIDL_PROGRAM_FILES, but something tells me this is a very unreliable method.
Any smart solution out there?
Is there a 'IsRunningFromProtectedFolder( )'-api that I do not know about?
Are there any other folders giving the same problems as program files do?
This is not a terribly good idea, as a user can install it wherever they want to, and then the check might fail. Instead have a checkbox when the user installs the app, deciding if it is installed locally or on a server.
As you I also found problems dealing with UAC folder virtualization.I suggest a workaround, it seems that it should work.
It comes from the assumption that elevated processes always use original copies and not the virtualized ones (CMIIW). Also I assume that you setup processed was executed elevated
The idea is to create a "general" process (non-elevated, legacy), that your main installer should run. This process will create a file name in the user chosen folder with a name and contents that both your programs know (for example, test73819704.bin). If the folder virtualized, this file should appear in the user VirtualStore and SHOULD NOT in the original one (from the point of view and privileges of the installer).
So for chosen C:\Program_Files_But_Not_Necessarily and Process-1 (elevated)
Process-1 ensures there's no file C:\Program_Files_But_Not_Necessarily\test73819704.bin
It launches Process-2 with no elevation
Process-2 creates C:\Program_Files_But_Not_Necessarily\test73819704.bin and checks whether it really exists. If exists it would return with a good return code, otherwise with a "failed" one.
Process-1 waits for Process-2 and analize the result. If good, checks for C:\Program_Files_But_Not_Necessarily\test73819704.bin, if it exists, go for "Bingo! No virtualization occured", if doesn't exist, "Bad, let's find some other storage place". If the code from the Process-2 is "failed" one, show the user some error message.
Unfortunately I could not test it right now, but I guess it should work and there's a logic behind this, with Process-2 you just emulate the behavior of your main program )
We allow our users to install anywhere...
If the user has taken the default, and is installed in Program Files, we make the assumption that we need to write to Documents and Settings/Users. Otherwise, we write our data to a folder under the directory the software is in. This of course can still cause problems, and the install does indeed allow people to choose a different data location if they choose to not go for the default.
On top of that, it's a simple ini file change and a copy to move the data.
On start up we detect if we are in the Program Files directory by comparing the value we obtain from SHGetFolderPath(CSIDL_PROGRAM_FILES) with the start of the path the executable is in.
We have a folder where our app will be potentially reading, writing and creating/deleting files on, and while we can default to a safe location, we allow the user to select a different directory. How can we check if the directory they select is "safe"?
We'd like to not require admin elevation at runtime, and this path will be used for subsequent launches of the app, so it is not enough that we check whether our process is currently able to write to that location because it could be that the app is launched with admin privileges the first time (actually it does when launched by the installer because the installer runs elevated) and if they select a protected location, the next time they try to run the app, they won't have access to the directory. Potentially GB's of Persistent data is stored in this location so asking for a new location and moving the files isn't an ideal solution.
Not only can any folder have any permissions, but they can change at any time, including between when you check a file and when you use it. So really, the only thing you can do is just use a file and handle the exception when it fails.
Since any folder can have permissions set however the administrator sees fit, the only real way to find out is to know what user it will be running as (currently logged in user?) and then do an access check to see if that user has the appropriate access to that directory.
The other advice about permissions changing at anytime is valid, but checking at install time is still better than not checking at all.
Since the first run will be elevated, what you probably want to do is launch a seperate non-elevated process to test the location, and then the original instance can proceed knowing that the location will work unless/until someone else changes the permissions.
I have a windows Application that stores certain files in a directory. I would like to know if there is a way in .net that I can restrict users not to have access to that directly (by just going to that directory in windows, and grab files) so only my application can add/verify/delete a file in that directory.
Could you use the Isolated Storage in .Net? While, it isn't necessarily restricted away from your users it may be a lot harder to find.... (stores under the local settings\application data\isolated storage for the logged in user)
Via code you work with it by using / importing the System.Io.IsolatedStorage and then you can create directories, files, etc... normal.
You also don't have to keep track of the actual directory on the HD it's in as .Net manages this. Maybe a nice plus.
This is only possible if your application runs with different credentials than the user running the application.
By default all applications run with the credentials of the user who launched the process. This means the application has the same directory and file restrictions as the user. Without a different account, the application can only decrease it's ability to access the file system, not increase it.
Dealing with the file system is evil in general. Even if you could get the user to not play in that directory you still can't trust the results will be in the exact same state as you left them. It's possible for other users, physical disk corruption or any number of other things to corrupt your files.
The only way to sanely program the file system is to expect failure from the start and count yourself lucky when it actually works.
The application needs to run as a specific user - and that user will always have the same rights as your application. You can, potentially, make a service that runs as an administrator to prevent standard users from accessing a directory, but the administrator will still be able to change things in the directory.
I suggest you look for another approach for your problem. There are potentially alternatives - perhaps you should consider keeping some type of encrypted hash on the directory contents. That would at least allow you to verify that the contents have not been changed, although it won't prevent the change from occurring.
As others have mentioned, you need the application to act as a different user than the ones currently logged in. You should look into 'impersonation', here are some links that can get you started on getting your application to act as a different user when performing certain tasks:
http://csharptuning.blogspot.com/2007/06/impersonation-in-c.html
http://www.codeproject.com/KB/cs/cpimpersonation1.aspx
The easiest (although not secure in any way) method, would be to use a hidden folder, which the users know nothing about. so \servername\hiddenfiles$
A more secure alternative would be to change the credentials the program is using to access the folder. Is it necessary for them to access it as themselves?
An alternative would be to create a dummy account for each user, where they do not know the password. Make it relate to their windows login, so domain\myname becomes domain\mynamehidden. Then use this to connect to the directory.
This will ensure everything can be audited nicely too.
Look at FileSystemWatcher - it doesn't prevent from changes in directory, but allows to notify program about changes in dir.