Cover V06, I08


Securing Your Web Server

Arthur Donkers

Connecting a Web server to the Internet will enable you or your company to present itself to a large number of potential customers. For small and large companies alike, this is often a very good way of offering support, products, and other services to existing customers. However, connecting your server to the Internet poses some security challenges as well. A large number of people use the Internet, and not all of them have good intentions. Furthermore, your competitors may take a shot at your server now and then to see if they can cause trouble for you.

All in all the goal is to be able to offer information on the Internet without exposing ourselves too much. This article will demonstrate ways to help make sure your Web server is safe and remains safe. It is based on the use of a UNIX machine as a server, so some of these tips may be UNIX-specific. Other tips are more general and could be applied to other platforms as well. These rules boil down to using a bit of common sense and understanding what you are doing.


A Web server is installed to offer information to anyone who is interested. This information is stored on the machine and must be protected from unwanted tampering. Furthermore, your server should be available 24 hours a day, 7 days a week, so you must make sure nobody can crash it or otherwise render it useless. By taking the necessary precautions, you can help prevent these problems.

In this article, I assume a UNIX machine has been installed as a server. The following discussion relates to features shared by all implementations, thus any UNIX will do. I have installed a version of the Apache Web server on the machine used for the examples. This server software is, at least according to the Apache team, the most widely used server software on the Internet.

Most of these tips apply to Intranet servers as well. However, most Intranet servers are connected to a controlled networking environment, which has (or should have) an established security policy. Furthermore, most people on an Intranet are not out to crash or demolish your server, so the need for tight security is not as high as for an Internet server.

Interactive Users

Your Web server, just like other computer systems, is an ordinary machine running a dedicated application (in this case Web server software and possibly some other related packages). So, most requirements for your normal systems also apply to your Web server, with a number of extras.

Typically, a dedicated machine is used as a Web server, so there are no interactive users running C compilers, database applications, or other resource-intensive programs on the machine. The only users allowed on the Web server are Webmasters and system managers. So, the first thing to do is :

1. Limit Direct Interactive Access to Your Web Server

The reason for this is simple; direct interactive users have a command shell on your server and can execute arbitrary commands. The ability to run such commands poses a real security risk because it potentially enables users to alter critical system files or to run programs that may crash the server.

Another side effect of letting interactive users work on your system is that they stop and start applications and tools and thus can vary the system load greatly. This will lead to varying response times for people accessing your Web pages. And since the Internet is already slow, you do not want to introduce extra delays.

Console Users

Although you can limit the number of direct logins to the Web server, you must also control the remaining user IDs that have direct access to the system. The first, and most secure, way to control such users is to limit their network access to the system - that is, force them to log in at the system console. By not running any network services that provide login access, direct logins must have physical access to the machine and log in on the console. This clearly limits the possibilities of a break-in via one of these routes. And, if your system is located in a secure area (e.g., in your regular computing center), you have a simple solution to the security problem.

If you need to load new pages on your Web server, you can store them on a diskette or tape from your development station. This tape is then transferred to the real Web server where it is read. The new pages are then stored in the active document tree on your Web server.

Although this procedure is a bit cumbersome and involves a lot of manual labor, it is the safest way of doing things. No one can connect to your Web server except through the Web port (which carries its own set of problems as discussed later).

Network Users

If direct access to the console is impractical or impossible, you will have to allow users in via your network. However, this should not be done casually, and a number of precautions must be taken to prevent unauthorized access via the network. I will mention several measures you can take to keep out unwanted users and let in the authorized ones. Not all precautions may apply to your platform, or you may need to install extra software.

Network access to the Web server can be limited, however, to essential services: telnet, so the authorized user can start a command shell, and ftp, to allow uploading new Web pages.

Note that running the telnet and ftp service on a port other than their default (23 and 21, respectively) does not make a secure system. There are a number of "scanners" available on the Internet that can discover all active ports on a host (e.g., strobe).

2. To Control Access on the telnet and ftp Ports, Install an IP Packet Filter on the Firewall

Some UNIX implementations have an IP filter already built into their kernel (e.g., Linux, FreeBSD). For other platforms like Solaris and HP-UX, a public domain IP filter is available that will do the trick. It is available at: \

This filter works on a number of platforms. Using this IP filter you can define which hosts (IP addresses) are allowed to contact your telnet and ftp ports. You will only allow machines from your local network (maybe even one or two local machines) to connect to the telnet and ftp ports. When defining these rules you must remember that the ftp protocol normally uses two ports, one for the control connection and one for the data transfer.

You do not want to install an IP filter on your Web port, because that may keep machines on the Internet from contacting your Web server. However, if you notice machines on the Internet trying to break in, you can always define a filter for those specific machines. By filtering the packets on the IP level, you will prevent many potential problems.

To prevent anyone from spoofing their way in, you will also need to install an access mechanism on a higher level. It is strongly recommended to use secure versions of the telnet and ftp programs. These secure versions are based on the Secure Sockets Layer (SSL) protocol (see my article, "Building a Secure Web Site," Sys Admin, Oct. 1996, pp 8-22).

SSL is the same mechanism used by secure Web connections for doing financial transactions. By using SSL you can both encrypt the connection between your Web server and your local maintenance station and authenticate both systems. An alternative to the SSL is using ssh (secure shell). ssh also offers both encryption of the data and authentication of both parties. However doing ftp over an ssh connection might prove to be difficult.

3. Disable All Other Network Services, Especially the smtp Service and inetd Services

You do not want to run sendmail on your Web server for incoming messages. Using sendmail for sending mail is okay, but using it for incoming messages is a bad idea. When you must have a mail server, run it on a dedicated and separate machine if possible, and preferably using a store and forward architecture. (This discussion is beyond the scope of this article, so if you are interested, drop me an email.)

Do not enable NFS, Samba, or any other network filesharing system. Enabling such services could mean that you are exposing other systems' files to anyone on the Internet who is interested in them.

Internal inetd services like chargen, daytime, echo, and such can be exploited in a denial of service attack that could render your Web server "deaf." So, do not enable those either. You can disable them by commenting out their corresponding lines in the /etc/inetd.conf file.

In an ideal world, the inetd.conf file would be empty and you would not even have to start the inetd program (the Web service is normally handled by a independent daemon that runs under its own control, and not under inetd). The possible exception could be a telnet and an ftp service protected by at least an IP filter (see previous paragraph).

So, if you were to run a netstat -a command on your firewall, you would only see the following services:

80     http, the 'normal' http port serviced by a standalone daemon

443    https, the 'secure' http port serviced by another standalone \

23     telnet, protected by an IP filter and possibly SSL or SSH

21     ftp (control), protected by an IP filter and possibly SSL or SSH

When you have done all this, you will have built a secure foundation for your Web server software.

Web Server Software

The next item on the list is the Web server itself. Because this can be a complex software package, it is bound to have bugs. Some of these bugs may lead to security problems. Another factor is the use of the standard system libraries that are available on the platform. A number of these libraries show a particular sensitivity to buffer overrun break-ins. In such a break-in, the hacker sends the software more data than it expects. If the input buffer is allocated on the stack (in C this is done automatically when you declare a variable local to a C function), the hacker can overwrite valid data on the stack, thereby forcing the function to jump into a piece of code sent along with the overrun data. (This was one of the tricks exploited by the famous Internet Worm of Robert Morris, and has been used a number of times since then.)

Although you cannot always prevent these problems, you should be using software that has been written with these things in mind and that is well supported. The Apache Web server software is a good example. It is claimed to be the most widely used server software on the Internet and is supported by an active team of programmers and contributors.

Soon after a security problem is discovered, a patch is made available to fix it. If you are using a commercial Web server package (like Netscape), you must make sure that the vendor is proactive in distributing security patches as well. In either case, it is a good idea to subscribe to the related mailing lists that carry the security alerts and patches. You will be notified of security problems and their solutions. It is recommended to take action as soon as such a message is issued, because issuing such a message will also alert (would-be) hackers who might try to break in using the information.

Web Server Configuration

So far, the tips have been quite easy and sometimes even trivial. I will now focus on the more complex issue of configuring the Web server and its associated features.

4. Run Your Web Server Software Under a So-Called Safe User

A safe user is one with almost no privileges - definitely not root. The reason for this is simple, if your Web server were running as root and somebody managed to break in, that hacker would automatically gain root privileges and be able to cause severe problems on your system.

Often the Web server software is run under the user "nobody," which was created especially for this purpose. This user should have a safe home directory located somewhere on the file system away from sensitive system files. You should also disable interactive access for that user by giving it a login shell as /bin/false. Additionally, disable the password for "nobody" by giving it a password of "*" (if passwords are stored in the /etc/passwd file) or "*LK*" (if passwords are stored in /etc/shadow).

"nobody" will also be a member of a special group, which is often called nobody as well. This effectively creates a completely separate user whose access to files can be controlled through the world permissions. Starting your Web server under this nobody account can be a problem when you use the default http port 80. This is a so-called privileged port that can only be opened by root, and not by an ordinary user. The Apache software has solved the problem rather elegantly by using a master process and a number of slaves. The master runs under the root user and receives a request. This request is handed off to an available slave, which will process it under the nobody account. Other Web server packages can do similar things, however make sure that you configure them in such a way that all requests are processed under a safe account, and not under the root account.

CGI Scripts

Apart from exploiting system misconfiguration, the most common break-in method is by taking advantage of Web server misconfiguration, especially with respect to the CGI scripts.

The Common Gateway Interface (CGI) is used to add real interaction to your Web site. It allows for the processing of data that is entered on forms, dynamic-generation Web pages based on the users visiting your Web pages, and much more.

When a user enters data on a form and presses the submit button, a number of things happen. First of all, the browser will pack all fields (both the field name and value entered by the user) into one string. Special characters like spaces are encoded so the string becomes a string of readable, non-space, characters. For example: do-a-script?Arg1=input1&Arg2=input2

(This is only an example; you do not need to try it.)

This string is the result of an input form that uses the GET method for sending the data to the server. The form has specified the "do-a-script" program as the ACTION parameter. The actual form contains two input fields, Arg1 and Arg2. The user entered input1 and input2 as their respective values.

This string is sent as a new URL to the Web server. The Web server is configured to recognize the /cgi-bin directory as a special directory that contains the CGI scripts. It will then execute the "do-a-script" program and pass the arguments (which in fact is the remainder of the string, starting at Arg1) in the environment variable QUERY_STRING to the script. This environment variable should then be parsed by the script.

Since this string is sent as a complete URL to the Web server, nothing keeps a potential hacker from building his own string and sending that off. By using improbable characters (which are normally encoded by the browser before sending them to the server), the hacker will try to exploit parsing errors in the script.

There is another way of sending the parameters to the script. The form can use the POST method instead of the GET method. The result is that the URL that is sent to the server now only contains the specification of the script, and is not followed by the encoded parameters. Instead, the parameters are sent to the script in a separate message. These parameters are presented to the script via the stdin (standard input) file descriptor. The script will then need to parse them as well. This method of sending the parameters offers no more secure way than the GET method. It is equally easy for a hacker to fake (e.g., by using the Net Cat program nc, or telnetting directly to the Web server port).

So, what is the risk involved in parsing these parameters? Both the Bourne shell and Perl have a special function called eval. The string that is passed as parameter to the eval function is processed (if needed) and then executed as a command. If you use eval as a way of splitting up your parameters, you have opened a nice can of worms. For example, suppose the hacker has entered the following string as the parameter string (mind you that he or she has entered this directly as a URL and not though a browser): do-a-script?Arg1=1;ls -l

When the following eval statement is used;

eval `echo $QUERY_STRING | awk 'BEGIN{RS="&"} \
{printf "QS_%s\n",$1}' `

this will finally result in executing the ls -l command in the cgi-bin directory of the server. The ls -l command is rather innocent, but you can imagine that there are more dangerous commands to be tried.

This is a rather explicit example, but there are more of these subtleties, some specific to the language used to write your CGI scripts. Some of them involve resetting the IFS (Input Field Separator character) to another value. This just demonstrates that writing a working CGI script is rather easy; writing a secure CGI script is a completely different matter altogether.

5. Never Install Your command interpreters in thecgi-bin directory

In the previous paragraph, I discussed the intrinsic problems involved in writing secure CGI scripts. However, there is an even more basic security problem lurking here. If you, for whatever reason, have installed the CGI script interpreter (like Perl, phf or Shell) in the very same cgi-bin directory, you may as well post your password file on the Internet.

I also showed that for the GET method, the parameters are passed in the URL itself, and for the POST method they are passed via stdin. Furthermore, the script that should be executed is specified after the cgi-bin/ directory. So, if you have installed Perl in the cgi-bin directory, anyone on the Internet can start that Perl, and feed it parameters (or a new Perl program to be run!) via stdin. This is like allowing anyone to execute an arbitrary program on your system without username or password authentication.

To conclude the list of items involved with CGI scripts, I have one last tip.

6. Never store your cgi-bin directory as asubdirectory of your document tree

Keep these items separate, it can save you a lot of problems when someone finds a hole in a CGI script. Furthermore, it prevents a user from obtaining a listing of the contents of your cgi-bin directory by requesting the documents in the cgi-bin directory.

With respect to the previously mentioned problems (you might call them challenges) you should make sure that no CGI script is run under the root account, for obvious reasons. While it might be necessary to read data from a database or obtain Web-related data in another fashion, do that under a restricted, unprivileged account. For instance, you could create a special user that only has access to a selected set of queries needed to retrieve the data you want to present on your Web pages. It is a good idea to give the Web server its own copy of the database, which only contains the data you want to present. Never give a Web server direct access to your real production database. Most CGI database tools are far too unrestrictive to limit their queries, so you could potentially give away all of your production data to anyone on the Internet. Remember that a potential hacker can build his own URL to call the query tool with whatever set of parameters the hacker may choose.

Newer versions of the Apache Web server (the 1.2 version anyway) allow you to specify the user id a CGI script is run under. This enables you to run these scripts under a different (possibly even more restricted) user that will have no access to the document root and other parts of the system. This is a new feature that will greatly enhance the security of your Web environment.

The Document Tree

7. Ensure that all files are accessible for the user your Web server Is running under

Setting up your document tree is similar to setting up anonymous ftp. It is best to have all files and directories owned by root. Only root has the permission to write files and add or remove files from a directory. The Web server has access through the group permissions; all files are owned by "group nobody" (the group that user "nobody" is part of). Make sure that the user "nobody" is the only member of the group "nobody." The other permissions of all files and directories are switched off.

This means that the owner permissions for a file become:


For a directory, these permissions become:


All files and directories are owned by root, and group owned by "nobody."

The net effect is that user "nobody" can only read files and directories, so the Web server software can only read these too. It should therefore not be possible to alter any Web page through the Web server. All files can be changed by root; therefore, only root can install new Web pages. Since user "nobody" is the only member of the "nobody" group, only he and root can access the pages.

Advanced Issues

8. Run your complete Web server in a chroot environment

You can ensure that anyone who succeeds (after all precautions we have taken) in gaining unauthorized access to your Web server can only do minimal harm by running your complete Web server in a chroot environment. By using a chroot environment you effectively lockdown the complete Web server software to a subtree of your filesystem. This technique is also used for anonymous ftp.

The chroot call will make the current directory the new root of the filesystem for the program that has called this system call. First, do a chdir to set the current directory to the location where you want to root your Web server. Then, do a chroot and after that, the Web server cannot access any files or directories that are not located beneath the new root.

Since you probably do not want to change the Web server software itself, a number of chroot wrappers is available. You can find one at:

Making your Web server run in a chroot environment, does pose a few problems. All files and libraries needed to run your Web server software must be copied to the appropriate subdirectory in the chroot tree. Try to use as many statically linked programs as possible. This will reduce the number of additional libraries you need to copy. It will also reduce the risk of a hacker overloading the system library with his own version. You will probably also need to copy a Perl interpreter to that chroot environment, together with all other programs.

Copying system files like the /etc/passwd file needs to be done with caution. Only the user ids you really need to run your Web server should remain in the /etc/passwd. Furthermore, the password entry itself should be replaced with an asterisk (*).

Although a chroot environment will not prevent hackers from altering your Web pages, it should reduce the risk of their gaining access to sensitive system areas. In particular, access to the real password file is prevented.


9. Monitor your log files

Most Web servers keep a log of accesses and errors. It is a good idea to keep an eye on these logs. You can even build yourself a filter that will alert you when something strange is logged (e.g., someone trying to start up non-existent CGI scripts). You could send these alerts via email to a dedicated account or have some other means of alterting the Webmaster or systems manager.

Security Audits

10. perform security audits regularly

To keep your Web server safe, you can run a regular check (or have it run by a specialized company). This will not only show you possible slip-ups, it will also make sure that you are secured against any new hole that may be discovered.


Your Web server is your virtual face on the Internet. If you want to keep this face clean you need to secure your Web server. By applying common sense and readily available means, you can build a secure server. The main thing is to only use what you really need, and no more.

Furthermore, once you have secured your server it is important to keep it safe. You need to do a regular checkup of your server, and preferably scan it regularly from the Internet. You can do this yourself or have a specialized company do it for you (like Le Reseau).

About the Author

Arthur Donkers graduated from the Delft University of Technology with a degree in Electrical Engineering and a major in Computer Architecture. Since then he has worked for several major software houses in the Netherlands. His primary field of interest is datacommunications, especially the security aspects involved. He now is the founder and owner of Le Reseau, a company specializing in security-related issues for UNIX, OpenVMS and Windows NT, and the application of Linux in corporate environments.