Scott on Writing

Musings on technical writing...

Another Potential Gotcha When Creating a Website that Allows Users to Share Uploaded Files

Many web applications I've worked on have had a requirement along the following lines:

  • A user should be able to upload a file from their computer, and other users of the site should be able to download and view these documents.

The specifics differ from project to project. For some projects, only certain users can upload files. In others, only certain subsets of users can view the uploaded files. In some cases, only authenticated users can view the files. In others, anyone can upload any file and these files are viewable by everyone.

When faced with such a task there are two design decisions that need to be made up front:

  • How are the uploads going to be stored?
  • How are the files going to be downloaded?

The uploaded files can be stored directly in the database or on the web server's file system. I've used both approaches in several projects, and the two ways each have their own pros and cons. I discuss the benefits and demerits of storing binary data in the file system versus the database in the four Working with Binary Data tutorials available from my Working with Data in ASP.NET 2.0 tutorial series.

If you choose to store files on the file system, then these files can be downloaded in one of two ways: by pointing users to the web-accessible folder the uploaded files reside in, or by creating an ASP.NET web page that takes in as a querystring parameter the name of the file to download and then streams the file to the visitor's browser. The second option is a must if you need to apply any server-side logic or actions before a file is downloaded. For example, if only certain users can download a file, then you would want to use the second option so that you can first ensure that the current user can view the requested file. Alternatively, you may want to log all file downloads or perform some other sort of bookkeeping, in which case having an ASP.NET page to process downloads is advantageous over sending the user directly to the file to download.

In a recent project we wanted to allow all users to download any files. In short, we had a page where any authenticated user (company employees) could upload company wide documents (like PDF press releases and whatnot) and any visitor - authenticated or not - could download the documents. For this model, it seemed to make sense to just have the files uploaded to a web-accessible folder. Then, on the page that listed the documents, there would be a link pointing directly to the PDF file (or whatever), like http://intranet/files/OctoberProfits.pdf.

Simple enough, eh? But can you see the security hole? What if a disgruntled employee created an ASP.NET page with inline code that deleted all of the files on the web server? He could then unleash his wrath by visiting http://intranet/files/DeleteItAll.aspx. Or, worse yet, the disgruntled employee might write an ASP.NET page that connects to the HR database and displays salary information. Whoops!

In short, whenever you allow a user to upload a document that is saved to a web accessible folder, and then you allow others to visit that document directly through their browser, there exists the possibility that a nefarious user will upload a script file so that they can execute code when the file is visited through a broweser. The best way to prevent this is to configure IIS so as not to allow script execution on the folder (and subfolders) where files are uploaded. That is, set aside a single folder where all documents will be uploaded, and then configure IIS to disable script execution on that folder.

In IIS 6, you can disable script execution by going into the IIS Manager and drilling down to the appropriate folder. Right-click the folder and choose Properties from the context menu. From the Directory tab, change the “Execute permissions” setting from “Scripts only” to “None”, as shown in the screen shot below.

With this change in place, if someone uploads a script file (such as a .asp or .aspx file) and then they (or another visitor) visits it through their browser, IIS will return an HTTP 403.1 error - Forbidden: Execute access is denied. Security hole plugged!

posted on Monday, January 14, 2008 2:45 PM

Feedback

# re: Another Potential Gotcha When Creating a Website that Allows Users to Share Uploaded Files 1/15/2008 11:38 AM Ryan

That might protect your server, but don't forget about your clients. A nefarious user could still upload a HTML file for an XSS or phishing attack, stealing your authenticated users' sessions and cookies or worse. Probably best to have a whitelist of content types and file extensions. Also, depending on how you are linking to the uploaded file, someone could upload a file with a "malicious" filename, which again could potentially redirect your user to a phishing site or worse.

# re: Another Potential Gotcha When Creating a Website that Allows Users to Share Uploaded Files 1/15/2008 12:01 PM Scott Mitchell

Good points, Ryan. There are a lot of little gotchas here for sure!

# Articulo: ¿Como incrementar la seguridad en sitios web que permiten upload de archivos? 1/17/2008 7:11 AM Guillermo G.

Un interesante articulo escrito por Scott Mitchell en el que nos brinda algunas consideraciones de seguridad

# Avoid potential security risks when uploading files to an ASP.NET app 1/21/2008 11:40 PM DotNetKicks.com

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Title:  
Name:  
Url:
Protected by Clearscreen.SharpHIPEnter the code you see:
Comments   

Add To Your Reader

My Links

Archives

Post Categories

 

I am a Microsoft MVP for ASP.NET.
I am an ASPInsider.
<May 2008>
SMTWTFS
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Comment Stats

DayTotal% of Total
Sunday 1866.8%
Monday 37913.9%
Tuesday 45316.7%
Wednesday 50418.5%
Thursday 53519.7%
Friday 49418.2%
Saturday 1666.1%
Total 2717100.0%

Hour1Total% of Total
12:00 AM 652.4%
1:00 AM 682.5%
2:00 AM 622.3%
3:00 AM 742.7%
4:00 AM 572.1%
5:00 AM 1033.8%
6:00 AM 1084.0%
7:00 AM 1585.8%
8:00 AM 1716.3%
9:00 AM 1475.4%
10:00 AM 1716.3%
11:00 AM 1816.7%
12:00 PM 1886.9%
1:00 PM 1696.2%
2:00 PM 1605.9%
3:00 PM 1324.9%
4:00 PM 1073.9%
5:00 PM 923.4%
6:00 PM 913.3%
7:00 PM 963.5%
8:00 PM 833.1%
9:00 PM 782.9%
10:00 PM 792.9%
11:00 PM 772.8%
Total 2717100.0%

Comments by Blog Entry Date/Time

Day Entry MadeAvg.Total
Sunday 5.54144
Monday 5.22339
Tuesday 4.28419
Wednesday 7.67637
Thursday 6.90607
Friday 5.48411
Saturday 5.33160
Total 5.842717

Hour1 Entry MadeAvg.Total
12:00 AM 5.0035
1:00 AM 1.002
5:00 AM 0.000
7:00 AM 7.0035
8:00 AM 5.35107
9:00 AM 6.32278
10:00 AM 6.47246
11:00 AM 4.41181
12:00 PM 6.88330
1:00 PM 3.00111
2:00 PM 5.41222
3:00 PM 8.64285
4:00 PM 4.0589
5:00 PM 5.92154
6:00 PM 4.52113
7:00 PM 9.67174
8:00 PM 9.80147
9:00 PM 5.05111
10:00 PM 5.4265
11:00 PM 4.5732
Total 5.842717

Learn More About Comment Stats
1 - All times GMT -8...


Blog Stats

Favorite Web Sites

My Books

My MSDN Articles