in reply to File Upload Security Question

Hmmm....

I NEVER allow users to set the filename on my server. You are stripping slashes from the user-supplied name, so you have the right idea. But, why open any security hole on your server?

Provide your own filename for any upload (since you do not allow outside access to these files, you could simply number them sequentially -- we normally create random filenames anyway), and then tie the real filename to the user's intended filename with a database, etc.

To expand on your actual question ("what type of security holes exist with a browse button?"), the issue is not the browse button. You can be relatively confident when planning for the data from a browse button (file upload). The people about whom you should worry are those who will submit to your server without using the built-in tools. These people will send you something the browse button never will. That's why we have to be paranoid, and never trust anything from userland.

It's a common misconception in most newbie CGI'ers: just because you provide (or don't provide) a button or field or a certain piece of data, you may never trust it. A user/would-be-hacker can easily submit false information to you. If you send a page with a Client Number in a hidden field, for example, you cannot trust that Client Number when performing any operation. Anyone could have forged it. Is it "The X-Files" with the motto "Trust No One!"? Believe it when doing CGI.

Russ

Replies are listed 'Best First'.
(jcwren) RE: Re: File Upload Security Question
by jcwren (Prior) on Jun 11, 2000 at 23:22 UTC
    I'm of a similiar opinion. But going one step better, don't use files at all. Use a database. Then you can attach all sorts of extra information that a file has no facility for (comments, user, number of downloads, yada yada yada). And DBs typically give you better flexibility if you have to start splitting machines to store data off from the webservers, etc.

    DBs also support atomic operations more readily. How are you going to handle two users uploading the same filename at the same time, assuming you don't support a mechanism like Russ proposes? The window for error gets wider if users are running on slow links (What?!? Everyone doesn't have a personal OC-12?)

    --Chris
      Okay, I have a slight confession to make. I was going to store the files in a database but I didn't know how to serve them back out to the users (hanging my head in shame). Since I have a very tight deadline (they start using my work the day after I am writing this), I just quickly went with what I knew to get it up and running.

      I'll be revisiting this after a week or so to clean things up (they'll use it for a week and then stop), so if anyone can point me in the right direction for serving files directly out of MySQL using CGI.pm and DBI.pm, that would be great.

      Also, I'm just storing the files directly, I do have a table in my database which stores the other information you mentioned. Wouldn't it be faster have the user link directly to a file rather than a script that will serve the file?

      As a side note, the group I am doing this for (who will remain nameless for legal reasons) is a non-profit group who couldn't afford to hire a really high-end Web development company, so I'm doing it for them for next to nothing. I think that's a mistake I'm not likely to repeat.

        You'll have to store some sort of ID with the file, perhaps the supplied file name from the upload routine.

        Since it goes straight into the database (be sure to quote it or use a DBI placeholder), you don't have to worry about the security implications of passing user data through the shell as part of an open statement.

        You can also use a simple SQL SELECT statement to pull the file out of the database: SELECT file from saved_files WHERE name = ?;

        Can you provide a little more detail on what exactly the sheets are composed of, etc? Are they HTML themselves, or are they fields from an HTML form? Does the data need to be reformatted on output, or is the data self-describing (akin to dumping HTML from a file straight out to a browser)?

        Here's an instance. If you were storing GIF or JPG files in a database, and you wanted to display them in a 2 x 2 table, for each TD in the table you have an IMG SRC tag that read something like IMG SRC="myscript_getimage.pl?item=x", where 'x' was some unique identifier (like an auto_increment field) from the database.

        The 'myscript_getimage.pl' would then be executed for each image to be displayed, and kick out the JPG or GIF.

        Conversely, if the file is some sort of data file that goes into another program (say TestGrader.tgf), when they clicked a link or a field in a table (use that JavaScript! Use that OnClick event!), you could download the file to their machine (via the save file dialog, like you most likely get when you download a .ZIP file). Or, you can register a handler for it, and open the application directly, much like downloading a .PDF typically does.

        There are lots of ways to manage data like this. If you can clarify your goals for the monks, I imagine we can come up with a suggestion to guide your down a more optimial path of elightenment. (Heh. Or you could see if you could get two dozen monks to collaborate, and turn your project into OpenSource).

        --Chris
        Personally, I'm inclined not to store the actual file contents in the database, because I feel that it complicates matters. My preference is to store the path to the file in the database, as well as any metadata about that file, then just store the file in the filesystem itself.

        When you want to serve a file (I assume you mean over an HTTP connection), you can just set up a script to grab the filename from the db, grab the metadata, etc. I'm pretty sure you could then just issue the correct Content-Type, then open up the file and spit it out to the browser. Be sure to use binmode if you're running on a Windows machine (or one that makes a distinction between text and binary files).

RE: Re: File Upload Security Question
by Ovid (Cardinal) on Jun 11, 2000 at 23:20 UTC
    The randomly generated filename works out nicely with what I am doing. The files are indexed with a table in a MYSQL database with autoincrement ids. I'm already adding the unique id to the title, so I suppose it's just a matter of stripping the user-supplied filename from the server filename.

    Thanks for the info!

RE:(2) File Upload Security Question
by swiftone (Curate) on Jun 12, 2000 at 19:27 UTC
    While Ovid has already changed this behavior, I'll give an example for anyone with a similar situation who may be reading the thread:

    Using your script (I believe), the user could upload a .htaccess file. The user could also upload a cgi file (for example), that the .htaccess allows to be run, and Poof!, the user now has full access to whatever the webserver id can do (On most systems this is limited, but does include just about everything on the website). In Ovid's example, the user could get access to the database, and twiddle any bits there (grades/scores?)

      I am also interested in giving users the ability to upload files to my website. Is it safe to allow users to upload a file as long as I name the file myself? I have an art business and I usually do drawings from photos. Ideally, I would like visitors of my site to be able to submit an image file to my site so I could give them a price quote for a drawing (or painting, etc). Do I need to take other precautions as well? Thanks, Rad (an humble newbie in Dallas)
RE:(2) File Upload Security Question
by Russ (Deacon) on Jun 13, 2000 at 00:58 UTC
    As a follow-up: I am nearing completion of a GPL package to provide secure file trading via web interface. It will offer temporary, expiring "visitor" accounts for outsiders' use, and will handle file clean-up on expiration, etc.

    This was just a sideline project, but based on the interest shown here, I now intend to finish it as quickly as I can.

    /msg me or send email if you're interested...

    Russ