Web Application Security Tips
CGI scripts at SEAS are restricted to running on Fling and Alliance. Even so, you need to avoid security holes in your web applications. Below are a number of common security issues that you should be familiar with.
1. Keep an eye on your file permissions.
Double check your file permissions: if you have given someone permission to read or write a file, and you both have Fling accounts, then their CGI programs have the same permissions, and a small programming error could give everyone in the world access to your files. This is especially true for "world" permissions: previously this just meant people with SEAS accounts, but now it really does mean "world".
It may be helpful to use the "File Security" option from within the SEAS Accounts Management Site to reset all file settings to only readable by you. Be careful, if you include your website in the reset, it will make it inaccessible via a web browser.
2. Restrict access to trusted users.
It's usually a bad idea to allow people without accounts to post to your wiki, forum, or blog. Spammers, phishers, and other malicious users often exploit open web applications for their own uses at the expense of you and your legitimate users. In addition, don't allow people to create accounts on their own without your explicit permission. Wikipedia and other large sites can get away with allowing open accounts to everyone because they have a large (volunteer) staff that checks every entry and removes inappropriate content within minutes after it is posted. In addition to inappropriate content (spam or just embarrassing), people can upload programs or commands and then trick your program or other users into executing the commands.
You either have to have a moderator check every submission before it is available to the readers, or you need to only allow submissions from trusted users (e.g. students taking your class). Even trusted users should have their input checked for safe format(strings) or viruses (files).
3. Be very careful with forms, especially file uploads.
All data submitted by a user should always be vetted before you do anything with it. Cross Site Scripting and other injection attacks thrive on unvetted data (see example below in #6). Scan files for viruses before accessing or allowing users to download them.
4. Separate dynamic content from static content, when possible.
If you have a static portion of your website that doesn't need dynamic scripting, keep it outside your dynamic directories (cgi-bin, dynamic, and wiki). It's also a good idea to save user uploaded files in non-dynamic directories to avoid a melicious user being able to execute code on the server.
5. Consider having your code reviewed.
Even the best coders can benefit from having someone else look over your code. If you are interested in a code review, please contact cets@seas.
6a. The dangers of trusting user input - a general example
Let's say that you create a simple blog that allows users to comment on your posts. Let's say someone decides to enter this as their comment:
Hi Bob, very gud job, keep it up! <img src="http://google.com/images/logo.gif" onload="window.location=’http://sam.com/’" />
Notice what will happen if your application does not sanitze this input and includes it on the page as-is. A user will come to view your blog entry, but will immediately be sent to "sam.com" without any action on their part.
6b. The dangers of trusting user input - a Perl Example
Let's say that the client enters an email address and the server sends a message to that address using
system("/usr/ucb/mail -s howdy $ADDRESS");
and the client enters the following "address"
chip && cd && rm -rf .
Then the command becomes
system("/usr/ucb/mail -s howdy chip && cd && rm -rf .");
The server was trusting the client to enter a valid email address
and nothing else, and the client took advantage of that trust.
The solution is to keep track of all variables that contain input from the client, and not to use those variables in any string that will be interpreted (eg, system or popen, or back-tics in perl or shells). If you must interpret untrusted strings, first check that they contain what they should. For instance, you could check that $ADDRESS matches the regular expression
[\w.+-]+(@[\w.+-]+)?
Using taintperl will help you keep track of variables that
contain untrusted information (tainted variables). If you are working
in perl, you should use taintperl for server programs. However, it
is still possible to write insecure programs in taintperl. To make
use of perl's taint-checking functionality use #!/usr/bin/perl
-T
as your perl interpreter.
Related Link
CGI Scripts on www.seas, Alliance.seas, and Fling.seas