URL-authorization and non-Asp.Net related file types - asp.net

URL authorization only applies to Asp.Net related file types?1 But why couldn’t it also be applied to non-Asp.Net file types?
Thanx

This is because of the script maps for ASP.NET. Only certain extensions are mapped into ASP.NET. The rest are handled directly by IIS. This is by design, for performance reasons.
There are two ways to handle this.
Duplicate your authorization rules in the web.config files in NTFS File ACLs (that is, set permissions on folders and files directly). Make sure that the user's authentication scheme matches the accounts and groups used for controlling access... in other words, if you're using SQL to store username tokens, this won't work, because those tokens won't necessarily map back to domain users and groups/roles.
Create an IHttpHandler to serve up your non-ASP.NET files. From the ProcessRequest method, call the Server.MapPath(url) method on the incoming URL, then stream out the file using Response.WriteFile(filename). You will probably need to set the ContentType property first. And, (here's the bad news), you may still need to perform a declarative or imperative access check -- just having the entries in the web.config files may not work. See Custom ASP.NET Processing with HTTP for more information on writing your own handler. It's probably a good idea to make separate handlers for each content type. Once you've written one, you'll see how easy they are to make.
You could try (haven't tried this myself) to add <httpHandlers> elements to web.config files where you have additional <authorization> elements -- use the <remove> element to remove the inherited HttpHandler and add another one at the subfolder level (perhaps pointing back to the same class?). I'm not sure this will work, but it's worth a try.
Finally, if you really don't want to go through and do all this work, you could simply add more extension mappings in IIS. For example, take a look at How to: Register HTTP Handlers, you can add a mapping for .jpg files to the aspnet_isapi.dll (take a look at the existing mappings for .aspx and so on). You do not need to add an HttpHandler element to your web.config, because the machine level web.config already contains this entry:
<add path="*" verb="GET,HEAD,POST" type="System.Web.DefaultHttpHandler" validate="true"/>
Please note that this may have very serious performance issues on your site.

Related

How to configure handler path to serve images from folder and database?

I am using a handler to serve images from database. I have a problem with the path configured for the handler.
<add name="DbFileHandler" verb="*" path="/images/db/*" type="DbFileHandler"
resourceType="Unspecified" allowPathInfo="true" />
The flow we want to implement is:
1) First Image is requested from a folder say "/images/db".
2) If the folder doesn't contains the image, the handler is called which fetches the image form the Db, displays it and writes the image to the folder
Also we have implemeted Imageresizer library to get images.
The problem here is when we request:
http://www.abc.com/images/db/101 -- Handler is called
http://www.abc.com/images/db/image.jpg?width=200 -- Image from folder is called
http://www.abc.com/images/db/image.jpg -- Again Handler is called instead of calling the Image from folder
How can we configure the handler so that a request to http://www.abc.com/images/db/image.jpg is not directed to the handler and instead served from "/images/db/" folder?
N.B: I would like to keep the path same i.e http://www.abc.com/images/db/
Are you using IIS express/full? If so, IIS is probably handling the .jpg extension as a static file and bypassing your handler. You need to set:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
This will ensure that IIS won't treat it as a static file and that your handler will run.
You'll then need to do the check manually to see if the image is there and serve that disk image if so, which is what IIS would do, but IIS would return a 404 if it wasn't found whereas you need to do your image processing and return the image data.
Please read the ImageResizer Best Practices.
Using ImageResizer properly, you only need to use DiskCache and the SqlReader plugin (Or build your own provider), and ImageResizer will handle request interception and (correctly threaded) caching for you.
Aside from the inherent performance limitations of using a HttpHandler instead of an HttpModule, under load you will create a lot of locked and/or corrupted files unless you implement a threading system that can coordinate the disk I/O.
I would strongly urge you to re-consider the approach you are taking here.

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

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.

How can I add location elements programmatically to the web config?

I have an application which creates page routes from a database. My whole site is secured with forms authentication but I need to allow unauthenticated uses to access these routes. I don't want to hard-code <location> tags for the routes in the web.config as this will negate me using a database to generate the routes.
Can anyone help?
Thanks everyone. I've found an answer here
Basically it involves creating a folder for each route and putting a web.config file in it allowing access. This approach needs to be coupled with setting RouteExistingFiles to false so that the routes don't get confused with the folders.
Rather than using strongly typed configuration classes, why not make the modifications directly in XML?
Here's an abbreviated snippet to demonstrate the concept from some code of mine that performance IIS tuning in the machine.config. The principal is the same for other XML config files though. You just need to create the appropriate XPath statements to do what you need.
XmlDocument machineConfigFile = new XmlDocument();
machineConfigFile.Load(MachineConfigPathString);
XmlNode autoConfig = machineConfigFile.SelectSingleNode(#"/configuration/system.web/processModel/#autoConfig");
autoConfig.Value = "false";
machineConfigFile.Save(MachineConfigPathString);
When saved, the XmlDocument object will preserve all other untouched document nodes. Very handy. It works great for modifying the machine.config. The only possible issue I can see is that your application will probably reset when you save your changes to the web.config. So test it out in a safe environment with a backup of your web.config just in case the reset causes any undesired outcomes!
I found this MSDN link for you. I didn't find whether you can modify the config of running server instance this way though.
Have you considered implimenting your site security in a different way? Having a portion of the site that allows unauthenticated access and a portion that does not. I am "assuming" (bad) that you are using MVC since you are describing routes - this is very easy to do with both MVC and traditional web form applications.

ASP.NET - Have settings in the Web.config (and access them using ConfigurationSection) or in a separate XML file

I have few settings which I could place in a separate XML file and have them accessed in the Web app. Then I thought (thinking of one additional file to deploy), why not have them in the web.config itself. However, just because I need to have custom nodes, I can not have the settings under . So, I am thinking of creating a custom config handler following this. Would that be better than having a separate XML file? Is It going to be an overkill or performance wise? Is there a better way to go?
From performance standpoint putting custom settings in web.config and creating a configuration handler will be OK because the config values are cached and read only once when the application starts. Putting the values in a separate XML file you will need to handle the caching your self if you want to avoid parsing it every time you need to access those values.

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