Home
Products
Forums
Help
Publish Article

Secure unauthorized download of ZIP files from your site by using HttpHandler

.Net Framework Version: 1.0, 1.1

I was working on an ecommerce web application for a site that sells software components. The final step in the process was to send an email to customer where a download link was provided to the ZIP file. I asked the question, what if I enter the URL to the zip file in my browser. Do you think the web application's implementation will be able to detect that I am trying to get your ZIP file without being authenticated to the site. The immediate response from one developer was, I have forms authentication enabled for the application. so you will have to authenticate first. Hmm.. do you think it is going to work, lets try it? To this developer's surprise, I was able to download the file without being authenticated. This whole conversation lead to defining the requirements of the download process.

  • We need a process to deny unauthenticated users access to download files.
  • We need a process to deny unauthorized users access to download file.
  • We need a process to hide the actual location of the download file from the user.

If you think it in terms of security principles, these 3 requirements directly translate to Authentication, Authorization and Obfuscation. So if we can fulfill these requirements of security, our job is done. So lets see what this means in terms of implementing this is ASP.Net application.

Authentication

Although you have set FORMS authentication for web application it does not stop anonymous user from accessing ZIP file directly. the reason is that your application is not configured for ASP.Net ISAPI extension to handle files of this type. You need a new file mapping in your application in IIS so that access to ZIP file is handled bt ASPNET_ISAPI.DLL. Once you have done that, every time somebody tries to access the ZIP file, the request will have to go through ASP.Net framework. And if you are not authenticated user, you will be redirected to Login page designated by your web application. Look at the Use ASP.Net to protect file types article to get more information on how to add file mappings.

Authorization

We solved our first requirement. Now we have the second problem. Consider this scenario. Customer A bought ProductX and he has registered with your web site. So now you send him the link to download ProductX file. Now he changes your download link URL and try to get to ProductY ZIP file. He is already an authenticated user so our first step is not going to prevent him from getting any other ZIP file that he is not authorized to do so. What about if I send a download link like http://www.mycompany.com/ProductX.zip?vc=DGH78W&pr=89TY03 to the customer? Now you are thinking, he is sending a URL that has some information sent in query string. Bingo... thats what we are going to do. We will send some information in query string which could be some authentication codes issued for that download to that particular customer. We process it to make sure that its the authorized user who is downloading the file. Now you are saying its all find and dandy but this URL points to a ZIP file. How am I going to process it? This is where our wonderful HttpHanlder is going to help us. You can read more about HttpHandler in .Net framework documentation. What I did was, implemented a HttpHandler for ZIP files and added the entry in Web.config file of the application. What this means is that every time a request comes for a ZIP file, ProcessRequest method of my handler is called. In this method I process the query string to figure out if user is authenticated and authorized or not. If he is not, I set StautsCode property value of Response to 404 so that user gets the message that file does not exist. And if he or she is the right user, response is redirected to the ZIP file.

<SYSTEM.WEB>
 <HTTPHANDLERS>
	<ADD type="ThirdEye.Web.HttpHandler.DldFileHttpHandler,
		 ThirdEye.ZipFileHttpHandler" path="*.zip" verb="*" />
 </HTTPHANDLERS>
<SYSTEM.WEB>

Obfuscation

So we have made sure that only authenticated and authorized user can access the ZIP file. But now you must be thinking that by redirecting the response to the ZIP file we have told the user the actual location of the ZIP file. And the requirement is that the user should not know about it. What I did was that in ProcessRequest method, after I verified the user, I read the ZIP file in FileStream and wrote the binary data directly into OutputStream of Response. Now user gets is a nice dialog box asking if he or she wants to open or save the file.

try 
{ 
  FileStream oFile = new FileStream(strPhPath, FileMode.Open); 
  ctx.Response.Charset = "";
  ctx.Response.ContentType = "application/zip";
  BinaryReader br = new BinaryReader(oFile);
  for (long l = 0; l < oFile.Length; l++)
  {
    ctx.Response.OutputStream.WriteByte(br.ReadByte());
  }
}
catch (Exception ex)
{
   Trace.WriteLine(ex.Message); 
   ctx.Response.StatusCode = 404;
 }

Final Thought

You must be thinking why go through the process of adding a new HttpHandler and file mapping, why not simply send a link to an ASPX page and then do the query string processing. You can do that too. But that does not prevent anonymous users to keep trying to access the ZIP files by trying different permutations and combinations of URLs. This way it is guaranteed that user is going to get access denied message is he has not authenticated himself.

Go Freelance
Home     About us     Contact us    Copyright    Privacy Policy    Return Policy    Advertisers
Copyright © Netomatix