Application Security Testing: An Integral Part of DevOps
A developer, working on a Web application that allowed only registered members to access a file, recently asked me if there was any way to control how the file could be downloaded. He had to avoid using the "gray box" popup dialogs because the access was controlled via the application. The answer was yes, but the solution requires several steps.
The first step is to store the file in a folder that is not directly in the Web root but is still accessible to the Web site's user ID (IUSR_machinename, for instance). My hosting customers keep their Microsoft Access databases one level above their www folders. The Web site still has access to read and write the databases in the folder, but users can't simply download the files directly.
The coding part of this requires you to create an ASP.NET page that has no HTML component but contains a code-behind block like this one:
FileStream liveStream = new FileStream(localfilename, FileMode.Open, FileAccess.Read); byte buffer = new byte[(int)liveStream.Length]; liveStream.Read(buffer, 0, (int)liveStream.Length); liveStream.Close(); Response.Clear(); Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Length", buffer.Length.ToString()); Response.AddHeader("Content-Disposition", "attachment; filename=" + originalFilename); Response.BinaryWrite(buffer); Response.End();
You can put this code in the OnLoad event, if you wish. The localfilename variable in the first statement is the path to the file on the server. The FileStream object (available in the System.IO library) gives you access to read a local file into the buffer that was created.
You then have to edit some information in the Response object so that the destination browser knows what to do. First, you clear the response and change the ContentType to the generic application/octet-stream. This typically causes the browser to display the Open/Save dialog. You then specify the length of the file and, if you have it, the original filename that you want to download. The example above stores the original file name in the database and changes the storage filename to one that is guaranteed to be unique.
Once you have the Response set up, you BinaryWrite your buffer to the user's browser, which causes the file to download. Once the user has downloaded the file, he or she is free to do whatever he or she wants to with it, but you at least can control access to the initial download of the file using this method.
About the Author
Eric Smith is the owner of Northstar Computer Systems, a Web-hosting company based in Indianapolis, Indiana. He is also a MCT and MCSD who has been developing with .NET since 2001. In addition, he has written or contributed to 12 books covering .NET, ASP, and Visual Basic. Send him your questions and feedback at firstname.lastname@example.org.