views:

571

answers:

4

The target web application is using ASP.NET 3.5 technology but I'm more interested in the intent of the list of checks to enforce on the server.

The following list is my initial thoughts, is there a better checklist out there? Are any of these thoughts misguided?

  • Limit file size at an HTTP infrastructure level.
  • Anti-virus.
  • Only allow supported file types (jpeg, png) by inspecting format. Do not rely on extension or HTTP headers.
  • Generate internal file name rather than relying on the one provided.
  • Approval process before allowing files to be accessed / displayed.
  • Store file / image in a sandbox before it is approved, especially if the file references do not require authentication.
  • Process file / image to a standard format and discard the original. Any legal implications of doing this?

Any guidance on implementing the checks would be appreciated, especially the anti-virus and image format checks. This is not a Webforms application so server side solutions (i.e. do not require Server Controls) are needed.

I've changed the title to use the words upload files instead of profile images to try and get focus on the intent of the questions. Thanks to cletus for the great suggestion of re-defining the requirement!

+6  A: 

The first thing that comes to mind is... don't. Instead use an existing avatar system like Gravatar or Pavatar. Why do you want to reinvent this particular wheel?

Second, since you're only concerned with images, I suggest you use a "white list" approach (ie define what is allowed rather than what's not). Use a library to validate that the file is in the correct format and accept popular image formats such as:

  • png;
  • gif;
  • jpg.

There's probably not any need for anything else.

Secondly make sure the file is no larger than the maximum (you define).

As for content, the only way to do this is approve images befor euse (laborious) or to allow users to flag particular profile images as offensive, much like the flag system here.

You can put the image in a standard format like png but that's purely optional and doesn't really gain you a lot (except that png has a better compression ratio than gif).

And of course you should choose the filename it's stored on your local system as. If you like you can remember the client's file name in case you want to allow them to download but again that's optional.

cletus
I like the idea of using an existing avatar system, thanks. Unfortunately our requirements on this particular project need the image for more than one purpose, including passing it on to an external system. Also how do you handle "approving" someone's avatar for display on your system or is this built into the solutions your pointed to?
Martin Hollingsworth
As far as using an existing avatar system, there's no reason you can't open an HTTP connection and get the user's avatar image yourself and then pass it onto an external system.Gravatar allows a user to give their image a content rating so it's self-classifying. You can report abuse by someone here http://en.gravatar.com/site/abuse/.If you want to approve images you'll need to build that yourself by uploading them and marking them as "not approved". Someone will then need to come along and mark them as approved.
cletus
All good responses and I'm warming to the idea. Need to really think about taking such a dependency on an external system though. I'm well aware implementing something ourselves is likely to have far more defects than these systems but it's still an external dependency. I'm still hoping to get some input on the original question of what checks should be done if you had to implement image upload. Haven't seen anything new yet.
Martin Hollingsworth
A: 

Process image to a standard format and discard the original. Any legal implications of doing this?

No. If the user is uploading an image, they're giving you permission to store it as you see fit. If they don't have the right to give you that permission, that's their issue, not yours. A ToS page is useful for avoiding lawsuits in the extremely unlikely event that someone takes issue.

Was going to cover the security issues, but was beaten.

pyrochild
A: 

Save the files under the new filename onto disk and a) configure your anti virus to scan on access (which should be default anyway) b) manually call your av to scan the file(s)

For the image format... I would load the image data into System.Drawing.Image, further process them (resize, etc.) and then save them out as jpg.

Markus Nigbur
+1  A: 

One you appear to have missed - where the files are stored and how you serve them.

You don't just store uploads in a temporary sandbox until they're approved, you keep them there. Uploads should go onto a separate drive if possible, and certainly not on the same drive as the operating system or a drive where log files are kept, it's all to easy to send lots of requests and fill the drive up. If they're on an isolated drive then the only problem is that new uploads will not be accepted.

If you want to address the images via straightforward HTTP, as opposed to going via a serving page (image.aspx?id={guid} for example) then make sure the directory you are uploading is configured so it has no scripting permissions at all - remove all the handlers except for authentication and authorization ones.

Be aware that HTTP uploads are processed entirely in memory - which is why limiting the request size is a good idea. However the request still has to complete before it's rejected for size so, for example, if you limit the upload size via

<location path="Upload">
    <system.web>
        <httpRuntime executionTimeout="110" maxRequestLength="20000" />
    </system.web>
</location>

and someone sends a 2Gb file that upload will still be accepted by IIS until it's complete and then rejected by ASP.NET. If 100 people send a 2Gb file then kiss your web server goodbye :) (Note the config format; we're just increasing the request length for one folder - rather than the entire site)

IIS7 changed this at little and has a built in maximum request sizes which (of course) takes precedence over the ASP.NET settings. You can only adjust this on a per application level, via

appcmd set config "Default Web Site/MyApp" -section:requestFiltering -requestLimits.maxAllowedContentLength:104857600 -commitpath:apphost

The default IIS7 request size is around 30Mb.

blowdart