Re: File Upload Security Question
by Russ (Deacon) on Jun 11, 2000 at 23:08 UTC
|
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 | [reply] |
|
|
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
| [reply] |
|
|
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.
| [reply] |
|
|
|
|
|
|
|
|
|
|
|
|
|
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!
| [reply] |
|
|
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?)
| [reply] |
|
|
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)
| [reply] |
|
|
|
|
|
|
|
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
| [reply] |
Re: File Upload Security Question
by plaid (Chaplain) on Jun 11, 2000 at 01:03 UTC
|
A few thoughts:
The $file variable which is the second parameter being passed in
never gets used anywhere. I don't know if this is because the
part of the code using it has been stripped out though.
The $data variable, third parameter passed in, just gets
overwritten in the while loop. Again, maybe something important
has been stripped from the code that I'm missing.
I don't see how $filename is a symbolic reference. A symbolic
reference only occurs when you're using one variable's value to
get the name for another variable. The code worked fine for me
without the 'no strict' lines.
The danger in this code lies in the open call. open allows
some powerful constructs in it, such as piping output to another
program, redirecting output, etc. Take a look at perlsec for
a detailed description.
| [reply] |
|
|
The issues with the $file and $data variables that you pointed out were caused by my stripping this down to a minimal test case and overlooking them.
You mentioned that you had no problem using the code without the "no strict" lines. Were you using this to upload a file from a Web page and using CGI.pm? That's where I seem to get the symbolic reference problem.
I'll take a closer look at the perlsec doc and see if it addresses the problem. Thanks.
| [reply] |