4

I'm working with the FileUpload in my project. And this project would be high visited (it's not my ambitions, just because web application does work with a payment system, that's why it will be under high-load). And I wonder, what's better for a storing the user's files? My project is based on ASP.NET.

I suggest two variants:

  • save as/load a BLOB object into/from database
  • save/load to/from a folder where the files will locate and save info about files in the table for owner recognizing, the table design in BNF:

<user_files> ::= ( <id ::= int, primary_key, auto_increment, indexed><user_id ::= int><file_guid ::= varchar(255)>) | nil

I prefer BLOB , but afraid of a future high-load. Because, fetching data from the database requires more CPU-time and memory allocations, because:

  • I need to use a connector, which will open a new socket to connect to DB localhost
  • Then must call stored-procedure for a getting BLOB object
  • at client-side, I must get the result from some classes from the connector
  • I must deserialize it
  • and only then just to send the file to a user in uncompressed and not corrupted state, so user can later open it in some editor (files often would be images and ms-office documents)

As I thought all these operations may decrease the server work and will require more time, I think it would be slow for a 2000 users online, which will exchange the documents very quickly

As for the storing files on the filesystem, I see only problem in:

  • securing correctly the access of files, because different users must not see others docs and they must be hidden for the other users. I'm afraid, because the folder to which users are uploading files is seen for the system user of Windows for the IIS (IISUser...), because otherwise users won't be able to upload anything, so the folder will be public. I see only solution to make a Windows Service and to use IIS folder for the uploads as temporary. Windows Service will get files from it and place to the secure folder, where users from web would be unable to see it.

But, maybe, I'm going wrong with my ideas, that's why I'm asking you a piece of advice, because I want to make system more perfectly.

Thank you!

Secret
  • 2,627
  • 7
  • 32
  • 46

2 Answers2

3

securing correctly the access of files

If you run into this situation you are already violation the OWASP security guidelines, since your files are insecure direct object references. This means that users can access files directly, because you opened a complete sub folder on IIS (like www.mysite.com/files/some_file.pdf) and your files probably have a name.

What you should do instead is:

  1. Register a file in the database with a unique; not its data, just its name and the user who uploaded it (optionally including rights or roles).
  2. Store the file on disk where the file name is the database identifier.
  3. Don't allow direct access but write a special HttpHandler that takes in the id of the document (just as you would do when storing the files inside your database).

When taking this approach, you achieve the following:

  1. Files have a unique number, which prevents them from having naming conflicts on disk.
  2. The HttpHandler can check the database of the user that downloads that file has the proper rights to do so.
  3. Because IDs are used, you are not vulnerable to canonical representation attacks, where the attacker does a request like this: www.mysite.com/file.ashx?file=..\web.config.

So from a security perspective, there is no problem in storing files on disk instead of your database.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • thanks for the advice, Steven, but the problem is, that ASP.NET project doesn't allow to upload files if I won't enable folder's access rules like this (for IIS-user, which is similar to what you've wrote): http://cs419427.vk.me/v419427458/62de/x_tCHnEWSfs.jpg , about "Don't allow direct access", so the temporary folder must exist and there must be rules for writing data to a folder, because otherwise there won't be any file-uploads, so what is best to do? make a Windws Service and use IIS-folder as temporary for uploading? – Secret May 02 '13 at 18:22
  • about the 3-rd option, my url in private zone is so encoded with a GET-params and cookies ( there are using AES and base64 modified algorithm, and also there is url-rewrite using ), so it would be too difficult to insert simply smth vulnerable to a URL body – Secret May 02 '13 at 18:25
  • The folder your website writes files to, should be located outside the IIS folder and the user that IIS uses to run your website should be configured to have read/write access to that folder. – Steven May 02 '13 at 18:29
  • it's diffidently strange for me, because ASP.NET website isn't able to save to any folder, which has a filesystem OS, because all files, which transferring by FileUpload forms in ASP.NET do use in CodeBehind smth like this: `System.IO.Path.Combine(Server.MapPath("uploads")` and you can't save files without using Server namespace, otherwise you'll get an exception with a try to save not in server folder, so it will be saved in any situation into the IIS's folder, because ASP.NET project hosts at IIS and it couldn't see lower level folders, than IIS's one. – Secret May 02 '13 at 18:37
  • You can always store files to any directory outside the website, but you can use the `FileUpload.SaveAs` method to write to any path, example: `fileUpload.SaveAs("c:\\file.txt")`. See this example for instance: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.fileupload.aspx/ – Steven May 02 '13 at 18:44
  • if you enable an access to a system root folder for the IIS-Users it's seems to be a more nightmare than saving to a subfolder at IIS folders, besides I've tried in my ASP.NET to save smth like C:\Program Files\project_name\user_uploads - I've got an exception even with the permitted rules to a folder, in exception were info about denying access to folders different from IIS pool... Alright, right now I will test again, then I report here about results, maybe I'm mistaken. – Secret May 02 '13 at 18:51
  • Not sure why you want to store those files in Program Files, you can pick C:\Uploads as well, or anything. But whatever you do, don't store those files on disk using the name the user provided you with (remember: all input is evil). – Steven May 02 '13 at 18:55
  • I'm not using the exact name at all, I'm generating Guid.NewGuid() for each new file and I don't want to trash a root directory of a system disk (that's why) – Secret May 02 '13 at 19:06
  • by the way you can see the topic, in which you can how I'm saving files ( I had answered in that question to myself also :) http://stackoverflow.com/questions/15950638/dynamically-generated-fileuploads-cant-give-options/15991654#15991654 – Secret May 02 '13 at 19:13
  • I've checked uploading files to other folders as you said. You were correct. Pervious experience failed only because of Windows policy for folder's on my server. Thank you. – Secret May 10 '13 at 11:24
2

Storing in a database will scale much better over time. If you use the folder solution, and someday you need or decide to use a cluster, synchronizing the files throughout the server farm will be hellish.

Even though fetching stuff from a database may be more CPU intensive, it does simplify a lot of things (your code will surely be more maintainable and portable), and you can always count on hosting and processing costs diminishing over time.

You can also cache stuff for speed. Either way I hope those files don't change a lot after being uploaded.

Geeky Guy
  • 9,229
  • 4
  • 42
  • 62