You are on page 1of 9


Application Setup

Put executables (code, scripts) in a separate directory, e.g. cgi-bin, outside the document root.
Do not mix code and html in the same directory. Mixing makes it easier for attackers to guess names and download code.
If you declare to the web server that all ".pl" files are programs, then the source of "" is not viewable. However,
editor backup files like "" or "" and files like "chargeit.old" and included files like
"" can still be viewed via the web.
So use a separate directory, e.g. cgi-bin, for code, rather than relying on suffixes.
Do NOT put general purpose interpreters, such as perl, PHP, or shells, in the cgi-bin directory.

Use one account, e.g. "webowner", to own the web pages and scripts, and another, e.g. "webrun", to run the server.
Do not run the server as root (UNIX) or the Windows administrator account. Port 80 servers on UNIX must start as root,
but then should change to another account.
The account that owns the server startup file and configuration file for the port 80 server controls which user it runs as.
On UNIX, the startup file and configuration file should be owned by root, and all directories in the path to these files
should be owned by root and writable only by root.

Do not use an account which has any special privileges (other than being able to read, but not write the web pages) to run
the web server. This will minimize the damage an attacker who has broken in via the web application may do.
"nobody" is often used on UNIX to run the server, but it is better to use an account not used for anything else.

For security purposes, it is best:

 to turn off automatic directory listings
 to turn off following symbolic links by the server
 to turn off the "exec" form of server side includes


A lot of popular, widely distributed CGI scripts contain bugs and vulnerabilities. Examples include older versions of guest
books, Count.cgi, the "phf" phone book script, and
See the World Wide Web Security FAQ, section 6, question Q5,
for a list of commonly used, vulnerable scripts.
In many cases, these or other vulnerable scripts came with your server as samples. Remove any sample scripts from your
server tree unless you absolutely need them and are sure they are safe.
Be very careful about downloading scripts from the web to use in your site.

Web Server Maintenance

Keep your web server, the languages it uses, etc. up to date.

Monitor appropriate lists for OS, web server, and language vulnerability announcements.

Hardening Hosts

 Use benchmark documents and scoring tools for hardening hosts and applications
 Disable web servers not in use - unused, unpatched web servers contributed greatly to spread of Code Red.
 Mirror all logs to a separate, locked down, logging host.
Application Design

Do not store session or sensitive data in the server directory tree.

If you do and attackers learn the file names, they can easily view them.
There are cases where sensitive information has been found and viewed via Google searches!
Create directories outside the server tree for session and sensitive data.

Input to the Server

 don't trust input to the server; check everything

 don't assume data you pass to a browser will return unaltered
 don't assume input is from a browser
When checking input, specify what is legal and reject all else, rather than trying to specify what is dangerous and
rejecting that.
For example, in a name field, accept the data only if it is a string of letters, periods, apostrophes, and hyphens - and
apostrophe's may be dangerous if you are using SQL.

If you use Javascript to validate form entries in the browser, you must revalidate in the server application, because there is
no guarantee Javascript was enabled in the browser, or even that the input came from a browser. For example, if the form
specifies a maximum length of 20 for a name, and it is checked again by Javascript, you still must check it in the server
The "referer" field passed to CGIs comes from the browser, and is therefore not trustworthy.

Remember: Don't Trust any Data from the Client

Server Languages

You can use Perl, Python, PHP, Java servlets, tcl, C, a shell, ... to implement the server part of the application.
None is perfect; all may be used securely or insecurely.
Perl has a "taint mode" which is very helpful in avoiding security problems.
Shell scripts are very difficult to code securely, and should be avoided.
PHP is difficult to use securely with the default configuration, and difficult to use when configured securely.
C has the best performance, but is harder to code and you must watch out for buffer overflows (use length checking
routines such as fgets() and strncpy() instead of gets() and strcpy()).

Maintaining State

The web is designed as a state-less system; each connection is viewed as completely independent of any other. Many
applications, such as e-commerce and web mail, need more.
Maintaining state involves passing information from one connection to another to form a session via:
 hidden variables, defined in the HTML for the page
 cookies, small files on the user's computer

It is a good practice to save the session data on the server, and use cookies or hidden variables just to pass a session
Since hidden variables and cookies are stored on the user's computer and may be viewed or altered by anyone with
access, they are neither completely private nor entirely trustworthy.
To improve trustworthiness and guard against replay attacks:
 check the host returning the cookie or hidden variable is the same one it was sent to
 provide for session time outs
 provide a way for users to log out, terminating the session
 encrypt the session id


If you want to save information beyond a session on a user's computer, use cookies. Typical examples are storing your
preferred language for a news or shopping site.
Unfortunately, there are a number of vulnerabilities in which cookies may be tampered with or stolen by other web pages.
Do not use them for sensitive information.
One option is to encrypt the stored copy of the cookies, but even so, it is best not to use them for sensitive information.

The Back Button and Caching

In many cases someone else has access to the same computer, e.g. a room mate, another user in an open lab, the janitor, ...
They may try using cached pages, bookmarks, or the back button to revive the web session.
HTTP provides a number of headers which may be used to timeout pages or direct the browser not to cache them.
Unfortunately, browsers often ignore those options; use them, but do not trust them.

Replaying logins

Even after your CGI or the browser decides a session has timed out, it may be possible for an attacker to use the back
button or a cache copy to go back to the login page and re-login. To prevent this, create a random key for each login page,
save it on the server and pass it to the browser in a hidden variable, and only allow the random key to be used once to log

Maintaining the Web Pages

A number of products for maintaining web pages use ftp to upload the new pages. This is susceptible to sniffing. Use a
product which can use sftp or secure web forms to upload pages.
If you log on to the server to update pages, use ssh, not telnet or rsh.


We will first examine web application vulnerabilities on the server, then those affecting the client.
The largest group of vulnerabilities (both on client and server) are due to the server not checking input and data from the
client; but it would be a mistake to assume checking data is all you need to do.

Don't pass important information via hidden variables!

For example, consider the web page, in which the price per widget is passed in a hidden (non-visible) variable:

The corresponding HTML is:

<INPUT TYPE="hidden" NAME="price" VALUE="10.00">
Enter number of widgets you are purchasing:
<INPUT TYPE="text" NAME="order" VALUE="" SIZE="8">
<INPUT TYPE="submit" VALUE="submit">

The application is passing the price as a hidden variable in the form. An attacker could easily save the form, edit it, and
send it back ordering 100 widgets at 1 cent each.

Vulnerability - Trusting Cookies

Cookies are stored on the user's computer, and may be altered by web pages or malware or by the user. Or the server may
be invoked by a script, not a browser. So don't trust cookies any more than you would trust a hidden variable.

Vulnerability - Buffer Overflows

Some languages, such as Perl, use dynamic storage allocation. Others, such as C, use static storage allocation.
When a C procedure is invoked, first the state of the program is saved on the stack. This includes the address at which the
procedure was invoked. Then the procedure allocates space on the stack for local variables, and then it begins execution.
When it reads or copies a string, if the string is longer than the space allocated for it, it overwrites adjacent variables. In
many architectures, the stack grows down so the string may overwrite the subroutine return address.

A carefully crafted string may allow the attacker to execute any code he or she wants, with the permissions of the web
server process.
For example, the following C code copies the query string from an environment variable to a local variable:

char query_string[30];
strcpy( query_string, getenv("QUERY_STRING") );

The form asked only for a phone number and the program allocates room for 30 characters, so this ought to be safe. But if
invoked by:
the query string will be longer than 30 characters and what happens is unpredictable.

In this case, the application should first use strlen() to test the length of the string before using strcpy() or use:
strncpy( query_string, 30, getenv("QUERY_STRING") )
to limit the copy to 30 characters.
Buffer overflows are most dangerous with stack allocation. They are less likely to be exploited with heap allocation. They
are not a problem with dynamic allocation languages such as Perl.

Vulnerability - Directory Traversal

Many web applications are designed to use a fixed program to display output, e.g. "". When passed the name of a
file, "" will display a page including the site's logo, left navigation bar, header, etc. and the contents of the file. A
typical call will look like:
However, if does not check its input, it is possible to display files other files.

The first is an attempt to display the source of the program "", to get clues about the application; the others are
attempts to get the /etc/passwd file.
Prevention: Don't allow "../" in input and check the names of any files to be displayed.

Vulnerability - Shell escapes

When an application invokes a function which starts up a full-fledged shell to run a command, this is called a "shell
escape". The danger arises because shells evaluate metacharacters, making it possible for intruders to run commands.
For example, the following perl code sends a message to the address in the variable "address":
open( MAIL, "| /usr/lib/sendmail $address" );
print MAIL "Your application has been received; thank you.\n";
close MAIL;
If the variable contains a real address, such as, then this will work fine.

However, if the address includes shell characters, this can do some damage, e.g. if the form address input contained:
nobody@localhost; /bin/rm -r /
Then the command string being sent to the shell is:
/usr/lib/sendmail nobody@localhost; /bin/rm -r /
which will send the mail to "nobody" (usually an infinite bit bucket) and then try to erase all files on the system.

Other problems with shell escapes arise due to not checking or resetting the PATH environment variable, use of shell
"magic" characters, etc.
Prevention: Don't use shell escapes. Instead, directly execute commands. In C, use "exec" instead of "system".
In perl, separating parameters by spaces causes perl to invoke commands directly, e.g.
system "/bin/ls -l";
will invoke the shell to invoke "ls", while:
system "/bin/ls", "-l";
will invoke the "ls" command directly. See your Perl manual for the syntax for pipes to bypass the shell.
Always specify the full path name of commands, e.g. "/bin/ls" instead of "ls" and delete the PATH environment variable
to minimize vulnerabilities.

Embedded Script Attack

Web discussion sites generally defend against embedded script attacks. This occurs when someone entering text into a
web blog or other discussion forum, includes active content which will do nasty things to unsuspecting reader of the blog
or forum.
For example, user A adds text to the blog:
Hi, I think that is great! <script>nasty_code</script>
Then when user B accesses the page, the code is executed on user B's machine and does its damage.
Neither user A nor user B have any privileged access to the server; however user A used the web server to carry out an
attack on user B's computer and the computers of other readers of the site.
Most web discussion sites guard against this by changing all "<" characters to "&lt;" and all ">" characters to "&gt;"
when displaying user comments. These are defined in the HTML 4.0 standard and will display as "<" and ">".
The same type of problem could afflict a web mail site. Try sending yourself some mail containing:
Then read it with a web mail system. If the system changes the "<" and ">" appropriately, then you will see what is
written above. If it does not, and you have Javascript enabled, you will see an alert box on your screen.
If the test failed, imagine what could happen if someone sent email containing harmful content.

Character Filtering

The embedded script solution is to filter "<" and ">". Why both? If you filter "<", then ">" should not matter.
Unfortunately, some browsers try to "correct" your mistakes and will interpret ">" as "<" if none of the latter occur. So
filter both.
There are over a dozen characters which could be dangerous in output generated from user input, including:
<, >, (, %, &, space, ...
Which characters could be dangerous depends on the context. No one guarantees they have a complete list. CERT, owasp,
various FAQs, all recommend validating by only accepting expected characters. All agree determining a list of bad
characters to screen for is the wrong approach.


The above solution to embedded script attacks assumes the IS0-18859-1 character set. There are character sets in which
"<" has two representations which are interpreted as the beginning of an HTML tag. In order to be safe, have the server
specify the character set, e.g.:

<META http-equiv="Content-Type"
content="text/html; charset=IOS-8859-1">
</HEAD> ...

See "Understanding Malicious Content Mitigation for Web Developers" , for more details.

Cross Site Scripting

Cross Site Scripting, abbreviated CSS or XSS depending on the forum, have been appearing with increasing frequency
It is probably misnamed; don't worry if the words "cross site scripting" don't seem to describe the vulnerability.
CSS is similar to embedded script attacks. However, in CSS, the attacker tricks the victim into clicking on a URL
containing the harmful scripting, of the form:<script>harmful_content</script>

The URL activates a CGI which includes echoing "user" input back to the user. The CGI may not filter characters because
it believes the submitter entered the characters, and doesn't need protection from him/herself. But the characters came
from the URL, not the victim.
Once again, the solution is for the server to remove dangerous characters from its output to be displayed. Better yet, the
server should not accept inappropriate characters. See the CERT paper mentioned above for what characters are known to
be dangerous and how to remove them.
For more information on CSS, see "The Cross Site Scripting FAQ", or
"The Open Web Application Security Project",", page 53 of the pdf.

Vulnerability - SQL Passwords

When using a database, you generally need to supply an account name and password. Most of the time, these are hard
coded into scripts. This is very dangerous; if an attacker somehow accesses your script, they can attack the data base even
without using the web.
It is much better to store the account name and password in a file outside the web directory tree, and read it to use it.

Vulnerability - SQL Injection

With SQL, the CGI inserts the input data into a string which is then submitted to an SQL server. The attack is to add
characters to the input so that extra SQL commands are performed or so the action is done on more database entries than
The way to prevent this is to validate user input before inserting it into an SQL request.
See the next slide for an example, or see the OWASP paper, or the "The SQL Injection FAQ",

For example (from Simson), assume you are getting the key for a database operation from the user's form, and using it a
sql_send("insert into names (name) value ('$name');");
What if the attacker supplies:
Oski Bear')"; delete from names;
in the name field of the form? Then the request is:
insert into names (name) value ('Oski Bear')"; delete from names;');
This has changed the original command into three commands.

Vulnerability - 404 Errors

Many servers allow you to replace the built-in "404 Page not found" by your own CGI. If you do so, make sure you
encode dangerous characters in the page you display. Otherwise if a user is tricked into clicking on a link like:<script>harmful_content</script>
and you echo the URL without filtering it, then the harmful script will execute on the user's computer.

Vulnerability - Canonicalization

When using extended character sets such as Unicode, which is used with Java, it may be that security checks on legal
input characters are done before the character translation is done. This may allow dangerous characters to be used. See the
OWASP paper for details.
Perl's Taint Mode

Perl has a special mode called "taint mode". When being used, Perl protects you from accidentally altering files and data
external to your program.
Taint mode is generally enabled by specifying the "-T" flag in the first line of the program file:
#! /usr/local/bin/perl -T"
Always, always use taint mode with Perl CGI scripts. It is painful when you first start to use it, but it is essential for
secure CGIs.
For full details on taint mode, see "man perlsec", your favorite Perl manual, or the "CGI/Perl Taint Mode FAQ",

In taint mode, you must set or delete the PATH environment variable before system calls; it is a good idea to also delete
delete $ENV{"PATH"}; delete $ENV{"IFS"};
You can not use raw input in a context which may cause harm, e.g. in system commands, or as part of the name of a file
being written. For example, instead of:
open( RESULTS, "> results.$year" );
$temp = $year;
if( $temp =~ /^(\d\d\d\d)$/ ) {
$year = $1;
} else {
die "*** input year not 4 digits ***";
open( RESULTS, "> results.$year" );

Address and Account Harvesting

Prevent spambots (web robots) from scanning your web site and gathering addresses by replacing "mailto" links by forms
and by obfuscating email addresses. See "Protecting your website's email addresses from being used by spammers",
for a variety of ways to do that.
If users need to login to your web server with an account name and password, make the user enter both the account name
and password before submitting the form, and then provide the same error name for a bad account name as for a bad


Techie tip - in UNIX, who can change the config. file with these permissions?
# ls -ld / /usr /usr/serv /usr/serv/jerry \
/usr/serv/jerry/conf \
drwxr-xr-x 69 root system 8192 Sep 11 08:13 /
drwxr-xr-x 34 root system 8192 Sep 11 08:13 /usr
drwxrwxr-x 11 root users 8192 May 5 10:42 /usr/serv
drwxr-xr-x 6 root system 8192 Jul 31 12:30 /usr/serv/jerry
drwxr-xr-x 7 jerry general 8192 Jul 17 14:56 /usr/serv/jerry/conf
-rw-r--r-- 1 jerry general 13239 Aug 8 2001 /usr/serv/jerry/conf/httpd.conf
Testing for Vulnerabilities

For the health of your career, get written permission in advance.