Web-enabled file storage and security implications of giving delete permission to IIS_IUSRS - asp.net

I've had this question for many years, and did research every time that this issue arose, but could never find a definite answer. Somehow the mighty Internet, MSDN, community forums, are either silent or vague on this. Out of thousands of development-related uncertainties, this is the only one that remained elusive.
To the point: in order to enable users to upload and manage images (and other files) used in their blog posts, in a shared hosting environment, I can either consider SQL Server binary data types (performance implications), or the file system. To use the latter, the necessary permissions need to be set for the IIS_IUSRS role on the storage directory : create/write, read and delete. My question - if I do this, what are the security implications? Could someone somehow take advantage of this, bypass the ASP.NET request pipeline and manipulate the files inside the folder without making a request to the corresponding ASP.NET handler (which checks rights, validates uploads, etc.)?
I've developed several systems that allowed file uploads and this has always bothered me. Now, hopefully, someone will be able to put my mind at ease and, ideally, explain the mechanics behind the process.
UPDATE
After viewing the latest answers (many thanks), another formulation of the question:
Is it in any way possible for a client to somehow bypass the request pipeline and create/delete files inside a directory that allows it (assuming the person knows the directory structure)? Or only the code that handles the request can do it? Any potential exploits?

The main problem is to been able to upload a script, an aspx page, in this directory with the photo files, and runs it.
Here is one case: I've been hacked. Evil aspx file uploaded called AspxSpy. They're still trying. Help me trap them‼
The solution to that is to add this extra web.config file on the directories that allow to upload files and not permit to run any aspx page. Also double check to allow only extensions that you permit and not allow to change that on the file name, if they have the opportunity to make rename.
<configuration>
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</configuration>
Also on the directories that you allow to upload files, do not permit to run any other script like simple asp, or php or exe, or anything.
general speaking
All your pages have permissions to run and manipulate many things on the server. What you give now is the ability of write on some directories, also by using some aspx page. The asp.net now have one more extra permission to write files there, on the photo folder. Also note here, that you asp.net page have this control, not the user. What you do there with your code can write on this directories, so must be carefuller there to double check where you write and not allow any other directories, not allow the user to manipulate the directory that can be written to.
So this is the weak link. To been able to upload more script that can take control of the server, at least the part that can be access by the asp.net user of this pool.

Having done this before, I'd make two recommendations:
First, do not store the uploaded files in the same directory structure as your application code (if possible). Make it a well-defined external location, and locked down explicitly to only the user the application is running as. This makes it harder for a malicious upload to be injected into your application as nothing in the web server, or ASP.NET itself, knows how to access the file (only your application).
If that is absolutely not possible to do so, be sure to make sure no external user can access the storage folder using standard ASP.NET authorization and only allow writes by your application user to this folder, nothing else.
Second, do not store the uploaded files with their original names and file extensions; Keep that meta-data separate. Just consider the file a raw binary blob of data. This is good for a couple reasons. First, it prevents inadvertent execution of the file on the server, be it by someone accessing the file system directly, the web server, or ASP.NET. Second, it makes it much more difficult for an attacker to exploit a malicious upload as they should never be able to guess the name, or path, of the file on the server.

Related

Prevent Direct Access To files ASP Web.Config

Strange question but hopefully its possible.
we have files in the root of our site (/files) these are uploaded through the main cms side of the website (/admin) and to be accessed by people who have access to the (/school) directory.
At the moment, if you have the direct link URL EDIT TO THE FILE you can gain access to the file
the files folder has its own web.config file with some rules, is there a way i can add some of my own authentication within the web.config to only allow requests that come from the School folder to have access to the files?
In my head i would have a piece of VB code that does something like this:
If (Request.UrlReferrer <> Nothing) Then
If Page.Request.UrlReferrer.ToString.Contains("/School/") = True Then
???
End If
Else
Response.Redirect("index.aspx")
End If
I've tested this in a simple page and it seems to work okay.
Well, I would assume that the users who can use school folder are memembers of a secuirty role called School (or some such).
thus, any user not a member of school can't use the pages (or files) in the school folder.
Since you want the SAME restricitons for the folder files, then use the same web.config to secure the files folder.
That will mean only users who can use the shools folders will also be the same group of people that only use the files folder.
Now the above will not stop members of securty role "school" from typing in any valid URL to the files folder. So, if you want to prevent this, then I would suggest that for all files up-loaded, you create a folder inside of files folder based on their PK row in the membership table (Memebership.ProviderKey).
Then what you would do is turn off all role groups rights to the files folder. I perfer not EVER allowing a direct URL to files.
Remember, only IIS respects the IIS security settings and provider for a web based URL. Code behind is 100% free to load, read, write, use, play with ANY file via code behind. Code behind uses plain jane FULL path names - and those path names and file names used by code behind does NOT care nor use IIS security settings. Only web based URL's dish out by IIS respect and use the IIS security settings you have for the schools folder. So, copy the web.config for schools over to files, and you are done.
But, code behind? it does not care nor use those settings at all.
So, code behind does NOT use nor respect nor care about IIS security settings. IIS role membership ONLY applies to the asp.net pages and web based URL's. But, code behind is a 100% free to get and grab any file on the system - even files outside of the wwwroot path name of the web site.
So, as a 2nd level and better security?
I would not allow ANY URL's to the files folder.
You then display a grid or list of files on the web page, and code behind for the download button can then go read/get the file (you can use TransMitFile to download that file)
So, best approach is to not allow ANY valid URL's to the files folder.
However, for now, since you only want people who can use the schools folder also be the SAME people that can use the files folder? Then just use the same web.config for both folders - only those people with role of "school" will thus have use and rights to the files folder.
From the information you provided, then you don't really need any code changes - only to take the security settings from the school folder web.config, and copy that to the files folder, and you should be done.
Now, it is possible that the schools folder is not secured by using IIS security and roles - but then again, that would a epic face plant and horrible design choice.

IIS Security: Why is it dangerous to make locally hosted xml files writable by the application pool account?

I have a website that reads an xml file, caches the file's object model, and i have web pages that read from the cache. I now want to make that xml file writable by the application pool account that runs the website so it can be managed by the website.
I've heard from peers that making that file writable is a security risk because if a hacker were to hack the website, he could potentially use the app pool account to overwrite that xml file and put whatever he/she wants into that file. However, since that file is read by directly hitting the web cache (and not the xml file) and the application pool account has write access to it, doesn't that mean a hacker can modify the object model that represent the xml file, regardless if the xml file is writable? By modifying the web cache, the hacker could inflict the same damage as if he had access to the web cache. I don't see how making the xml file read-only makes the website safer from hackers.
If I understand correctly, your xml file is read, turned into an object or a collection or some .NET data structure. And presumably only xml files of a certain schema can be successfully read this way.
I guess this depends on if there is something interesting in the xml file. If the xml file is the list of administrators, then as a hypothetical hacker I'd like to modify that file and add my name to the administrators list, which will result in an xml file that still serializes and deserializes to the data structure previous defined in code.
Another way to use write ability, would be to update a price list so that the prices are all free or heavily discounted.
If the XML file is a list of US states, then even if I could modify the list, I'm not sure what I could do with it outside of mischief, which is a larger concern for internet apps than for intranet apps.
I would put the file in the App_Data folder so that it can't be downloaded directly, which will make it harder for a hacker to make correct modifications to it... but security through obscurity is not really a good plan on it's own.
If the hacker were to hack the website, then security is compromised anyway. Allowing write access to the XML on it's own shouldn't be an issue, but I wouldn't give this access to any other files within your website.

web.config ignoring certain files from requiring authentication

In my asp.net web application, I have a folder in which I have a few html and jpeg files. some of these files do not need a user to login while the others do. How do I exclude the files that are free for view to be displayed without logging in while still maintaining the user to login for viewing other files in the same folder using just the config file. I wasnt able to find something relevant in the config file or maybe I overlooked it. If anyone knows please reply.
Thanks.
I've tried to answer this as well as I can but the sentence:
How do I exclude the files that are free for view to be displayed without logging in while still maintaining the user to login for viewing other files in the same folder using just the config file.
..is a bit confusing!
The files that need to be authenticated are the ones that are handled by the asp.net handler such as .aspx files. jpegs and other static files bypass this so can be viewed without authentication. The handler aspnet_isapi only handles certain files but you can configure it to handle more file extensions (or all files) by configuring extension mappings in IIS.
Personally, I would put all files I wanted to be unprotected in a folder with permissions to allow anyone to view that folder, set the aspnet_isapi handler to handle all files and then protect your other folders according to your application's needs.
Depending on what you want to do (as your question isn't that clear), you may or may not be able to achieve what you want just from the config file but hopefully this answer will give you the information you need to make your own conclusions on that.

ASP.NET Web.config question

The server is IIS7.
Is there a way to disable web.config files in subfolders?
I am asking because, I have a folder on the web server that is for uploads. When someone uploads files, a new folder is created for the user's session and the files they upload go in the folder.
So the path to uploads would be like this:
~/uploads/3F2504E0-4F89-11D3-9A0C-0305E82C3301/somefile.txt
In the ~/uploads/ directory there is a web.config file that removes all http handlers except the static file handler and adds a wildcard mime type. So every file that a user uploads will only ever be served statically.
If a user uploads a web.config file, I want to disallow any of the settings in that file from being applied.
How can I do this?
EDIT
Could I just make the upload folder an application that is a member of an application pool configured to run in Classic mode instead of Integrated Pipeline mode? That way it wouldn't even care about a web.config file.
EDIT 2
Is there another type of webserver I could install for serving all files statically? I could just access the files through a different port. Is there some software that I can be sure wont run any scripts and is safe.
I simply wouldn't allow them to upload a file with that name. In fact, I normally wouldn't trust any filename that the user gave me... makes a great candidate for an injection-style attack.
Ok I have a different angle on this...
What if your uploads folder was not part of the website and instead part of the file system? This way ASP.NET is not processing requests to the folder and thus web.config wouldn't be loaded by the ASP.NET runtime.
You'd have to give your app pool's account read/write access to the file system where these files are stored, but I think it better fits what you're trying to accomplish.
Obviously it could be done in code.
If the folders always exist, you could pre-populate with a web.config with no (significant) content and an ACL to ensure it cannot be overwritten, but looking at the path it I suspect you create the upload folders dynamically which means this would not work.
I don't believe there is a way to tell IIS not to use a web.config (but I could be wrong). Personally, I would add a check to my save code and rename the file.
Why not just check the filename first to prevent the user from uploading a file named web.config? You're probably going to want to check for other things too before allowing the upload - files that are too big, etc.

Uploading files to my site

I have an ASP.NET application. I want users to be able to upload documents. Where in the file system should I store those documents? Users should be able to upload them and see the hyperlinks to them on the site, but UserA should not be able to see UserB's documents, but the administrator role should be able to see all of them.
I'm assuming I don't want to upload them to a folder with my web application because then the web server can serve them up directly. I don't want to store the file in the database, but I can store file paths in the database.
Somebody please give me some best practices. Thanks!
Depending on the size of the files, one options would be to store the files outside the web root so no one could hot-link to them, then, as has been suggested, produce a page that takes some arguments and Response.WriteFile() from said directory.
If the files are large you might want to use Response.TransmitFile to save on some memory on the server.
From an implemenetation point of view, I would probably store the real name of the file in the database to avoid naming collisions and save the files on disk renamed to something like a GUID or just an integer ID taken from the database table.
Then when you write the file to the output stream you can use a content disposition header to rename the file back to the original name.
HTH!
You probably want a folder structure with one folder per user. You could write your own CreateFolder() method that after creating the folder adds a web.config file with authorization rules, letting only the user and administrators access it. That way, users can only access their own files, but admins can access all.
EDIT: For clarification - I am assuming that you are using the ASP.NET Membership features (although not necessarily exactly as is), which lets you put individual web.config files in a directory with the nodes shown below to control access.
<configuration>
<system.web>
<authorization>
<allow roles="admin" />
<allow users="TomasLycken" />
<deny users="*" />
</authorization>
</system.web>
</configuration>
Another way of doing it, is to place all the files in one place, to which you statically allow no access to anyone, and then have a generic handler (.ashx) which serves the files after looking up url and permissions from the database. This is probably a cleaner approach, and it will also take less space seeing as you won't have tons of web.config files laying around...
Note: I purposely posted this as a separate answer, so you can mark the solution you prefer as your answer and ignore the other one.
You can create a virtual directory adjacent (as a sibling) to the root of your website in IIS this does a couple of things 1) it prevents users from accessing the files directly by guessing the file location, 2) you can point the virtual directory to any location you wish, 3) with directory browsing turned off you can prevent anyone from seeing the structure. You can then store the paths in a database further removing the actual structure from the clients.
I have implemented solution like this. I store files in the protected (via web.config section) folder within the website, but instead of real file names I used guids. I also had a database that mapped guids to real names and had some extra information like file size, type etc. In your case this information could also contain name of the user that uploaded the file.
To download the file I implemented HTTP handler that would get a guid parameter and based on the file type set appropriate HTTP header and write the content of the file into response. Before I write file to the response I also check permissions for the current user. Then I have a page that render a list of file names as hyperlinks that point to this HTTP handler with guid parameter that correspond to particular file in the protected folder.
For upload I used very nice SlickUpload control:
http://krystalware.com/Products/SlickUpload/

Resources