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   

My Links

Ads Via DevMavens

Archives

Post Categories

 

I am a Microsoft MVP for ASP.NET.
I am an ASPInsider.
<March 2010>
SMTWTFS
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Comment Stats

DayTotal% of Total
Sunday 2056.8%
Monday 42514.1%
Tuesday 51917.2%
Wednesday 55518.4%
Thursday 58019.2%
Friday 54718.1%
Saturday 1886.2%
Total 3019100.0%

Hour1Total% of Total
12:00 AM 782.6%
1:00 AM 812.7%
2:00 AM 682.3%
3:00 AM 822.7%
4:00 AM 692.3%
5:00 AM 1264.2%
6:00 AM 1183.9%
7:00 AM 1816.0%
8:00 AM 1926.4%
9:00 AM 1585.2%
10:00 AM 1886.2%
11:00 AM 1936.4%
12:00 PM 2016.7%
1:00 PM 1846.1%
2:00 PM 1695.6%
3:00 PM 1354.5%
4:00 PM 1153.8%
5:00 PM 1073.5%
6:00 PM 1013.3%
7:00 PM 1073.5%
8:00 PM 923.0%
9:00 PM 882.9%
10:00 PM 913.0%
11:00 PM 953.1%
Total 3019100.0%

Comments by Blog Entry Date/Time

Day Entry MadeAvg.Total
Sunday 4.97159
Monday 4.80384
Tuesday 4.04477
Wednesday 7.39680
Thursday 6.26676
Friday 5.07466
Saturday 4.78177
Total 5.403019

Hour1 Entry MadeAvg.Total
12:00 AM 5.2937
1:00 AM 1.002
5:00 AM 0.000
7:00 AM 3.8550
8:00 AM 3.72134
9:00 AM 6.06297
10:00 AM 5.63276
11:00 AM 4.22194
12:00 PM 6.16351
1:00 PM 3.09133
2:00 PM 4.89230
3:00 PM 7.64321
4:00 PM 4.00108
5:00 PM 6.07170
6:00 PM 4.64116
7:00 PM 8.95188
8:00 PM 8.63164
9:00 PM 5.00115
10:00 PM 6.31101
11:00 PM 4.5732
Total 5.403019

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


Blog Stats

Favorite Web Sites

My Books

My MSDN Articles