How to configure handler path to serve images from folder and database? - asp.net

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.

Related

Path traversal vulnerability

The concept of path traversal is new to me need some guidance please.
In my project I have following line of code:
uploadimg.SaveAs(Server.MapPath("tempfiles/" + fUIName));
FileUpload1.SaveAs(Server.MapPath("tempfiles/" + fSIName));
Is this code is vulnerable to PathTraversal vulnerability.
Can any one help me understanding the concept of path traversal and how to remove/avoid it.
Thanks!
Edit 1:
It is also mentioned that I am storing files in tempfiles folder temporary. After the purpose of saving the file fulfilled I am deleting the files from tempfiles. So can I skip this vulnerability?
Please guide.
Thanks!
The path traversal is means that some one upload a file to your site and can access it direct from the URL (if he knows the path, or can find it from some other page).
Eg, lets say that you upload a pdf file named file.pdf at tempfiles/
Then you probably show it on some page as http://example.com/tempfiles/file.pdf
Now the attacker knows where the file is uploaded, and then its upload to you some other file, maybe an html with fraud, maybe some server browser in an aspx page etc... and direct call it from the url.
Solutions
You can upload all the files to a secure folder like App_Data that you can not direct access it.
You can upload it to a folder that you change the permissions and again you can not direct access it. (see here how you can do that How to set correct file permissions for ASP.NET on IIS)
You can limit the extensions for what you upload and let only images for example, and put that on that directory to avoid anyone to run anything there.
<configuration>
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</configuration>
Now, if you upload pdf to a directory that the user can not access direct from the url, you need to create a handler that return the uploaded files. The handler must knows if the user is allowed to view the file, if the file is safe, if the file come direct from the site.
some simple examples.
file download by calling .ashx page and Alternate image display in asp.net
And one last solution is to check the reference and make sure that is comming from your site and its not a direct call from the url using this HttpContext.Current.Request.UrlReferrer.Host. Meaning that the user is uploading an image, but its allowed to view it only if its come the request from a page of your site using some link.

Disallow some file extension from being browsed

I m using Asp.net mvc to get my web site and it is used to show some files uploaded by the admin.
There is a directory (Upload) and admin puts the files on it.
Now the thing i want to know is that no one can access the file by just browsing the url below.
'www.mysite.com/Upload/somePdfFiles.pdf'
Now i want to disallow 'pdf' extension to be downloaded.
Alternatively, i m going to design a page and i m going to get the file path by query string,session etc so that i can download the file by myself. In this page i m going to check some privilege.
So how to disallow 'pdf' extension to be browsed.
I don't think that's possible - you can't differentiate between viewing and downloading because ultimately the actual file content is sent down to the browser and that content is accessible by either saving a document, or by directly accessing the HTTP content with an HTTP client or an HTTP Proxy that can capture the downloaded data.
You can deny access to files in a number of ways so that they are not accessible at all, but you can't make a file 'read-only'. To deny access you can disable access to certain extensions using either IIS filtering, explicit Location exclusion (in web.config) or mapping the extension of choice to the HttpForbiddenHandler.
Whether you view a file as a document in browser or downloaded is determined via HTTP headers. If you don't explicitly specify a Content-Disposition: attachment; filename=<filename> in your headers, the browser will try to open the downloaded content inside of the Web browser using appropriate viewer. For PDF this usually means it'll show in the built in PDF viewer or installed PDF extension. But even if people use the viewer they can always save the document from the viewer so you can't make that content read only.
See HttpForbiddenHandler Class and use in your httpHandlers settings.
e.g.
Restrict links/direct requests to PDF files in /files folder only (403)
<system.webServer>
<handlers>
<!-- If you want to restrict all links
<add verb="*" name="RestrictPDFGlobal" path="*.pdf" type="System.Web.HttpForbiddenHandler"/>
-->
<add verb="*" name="RestrictPDF" path="/files/*.pdf" type="System.Web.HttpForbiddenHandler"/>
</handlers>
</system.webServer>
Alternatively, i m going to design a page and i m going to get the
file path by query string,session etc so that i can download the file
by myself. In this page i m going to check some privilege.
You could do that (interesting note below) by privileged access - e.g. [Authorize] attribute
Sample, improve as needed:
in Home Controller:
[Authorize]
public FilePathResult DownloadPdf()
{
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "foo.pdf"
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File("~/files/foo.pdf", "application/pdf");
}
View:
<p>#Html.ActionLink("PDF Download", "DownloadPdf", "Home")</p>
Note:
The interesting thing here (I don't know the answer), is why the restriction set in config "allows" this approach (where we "manually" return it via Controller -> Action vs a "direct" request like in a link).
Hth

Not able to access session in Httpmodule for static resources like css /js/ image files

I have created a HTTPModule. Session information is retrieved using PreRequestHandlerExecute. It is working well for aspx pages. But while loading css/js or any image files, Session is null.
I have gone through the link ASP.NET CSS file not loaded when adding HttpModule to web.config
But could not get the implementation.
Anyone has any idea about this?
I think you'll find that your static files are being handled by the StaticFileHandler and as such wouldn't fire off session events as the session won't be being activated for efficiency purposes.
You could configure IIS to pass static files through a different handler (the PageHandler for example) but really you'd need to know if that was required first. You haven't described why you want sessions to be available for static files.

httphandler filetype mapping requires virtual directory (or does it?)

I am using an httpHandler to pass all requests for *.gif files to an ashx handler. i only want to do this for requests to a sub-folder within the website. The website root is called 'demo' and the subfolder is called et. So, I add a web.config file to the et folder with an entry as follows:
This is not enough to pass all *.gif requests to the ashx - I also need to add an application extension to point requests for .gif files to aspnet_isapi.dll. i can't find any way to do this apart from make the et folder a virtual directory (which I don't really want to do). Anyway, I set the et to a virt dir, then set the mapping and it all works. If I then remove the virt dir app for et the whole thing keeps working. This suggests to me that there must be a way to set the *.gif mapping without having to create a virt dir and then remove it again.
Anyone know what's going on here?
Thanks very much.
Did you set up the handling with IIS as well as ASP.NET? I know I had issues with that because IIS gets the request before ASP has any chance to do anything about it.
If you're using IIS 7.0 I recommend you use the new integrated pipeline. This kind of issue will jsut go away. I succesfully implemented Http handlers for directories without doing anything special configuration, just add the following to the httpHandlers node:
<add verb="GET" path="et/*.gif" validate="true" type="YourGifHttpHandler" />
Hope that helps.

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

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.

Resources