Orders Orders Backward Forward
Comments Comments
© 1997 The McGraw-Hill Companies, Inc. All rights reserved.
Any use of this Beta Book is subject to the rules stated in the Terms of Use.

Chapter 4

Firewalling Challenges: The Basic Web

This chapter discuss the challenges firewall implementations face in light of the HyperText Transmission Protocol (HTTP) and some of its security issues. It also discusses the proxing characteristics of HTTP and its security concerns. It explores the secure HTTP (S-HTTP) as well as the use of SSL for enhanced security and reviews the security implications of Common Gateways Interface (CGI

HTTP

Being an application-level protocol developed for distributed, collaborative, hypermedia information systems, the Hypertext Transfer Protocol (HTTP) is a very generic and stateless protocol, enabling systems to be built independently of the data being transmitted. It is also an object-oriented protocol with capabilities to be used for a variety of tasks, which includes but is not limited to name servers, distributed object management systems and extension of its request methods, or commands.

One of the great features of HTTP is the typing and negotiation of data representation. This protocol has been in use since 1990, with the W3 global information initiative.

The most current version of HTTP is version 1.0, which is supported by all Web servers in the market. But there is also another version of the protocol, HTTP-NG (Next Generation), which promises to use the bandwidth available more efficiently and enhance the HTTP protocol.

Further, HTTP is a protocol that can be generically used for communication between user agents and proxies or gateways to other Internet protocols, such as SMTP, NNTP, FTP, Gopher and WAIS.

Nevertheless, all this flexibility offered by HTTP comes at a price: it makes Web server, and clients, very difficult to secure. The openness and stateless, characteristics of the Web, accounts for its quick success, but makes it very difficult to control and protect.

On the Internet, HTTP communication generally takes place over TCP/IP connections. It uses as default port 80, but other ports can be used, which does not prevent HTTP from being implemented on top of any other protocol. In fact, HTTP can use any reliable transport.

When a browser receives a data type it does not understand, it relies on additional applications to translate it to a form it can understand. These applications are usually called viewers, and should be the one of the first concerns you should have when preserving security. You must be careful when installing one, because, again, the underlying HTTP protocol running on your server will not stop the viewer from executing dangerous commands.

You should be especially careful with proxy and gateway applications. You must be cautions when forwarding requests that are received in a format different than the one HTTP understands. It must take into consideration the HTTP version in use, as the protocol version indicates the protocol capability of the sender. A proxy or gateway should never send a message with a version indicator greater than its native version. Otherwise, if a higher version request is received, both the proxy or the gateway must either downgrade the request version, respond with an error, or switch to a tunnel behavior.

Note:

If you need more information on HTTP, check the URL: http://www.w3.org/hypertext/WWW/Protocols/

There is a series of utilities intended for Web server administrators available at the URL: ftp://src.brunel.ac.uk/WWW/managers/

The majority of HTTP clients, such as Purveyor (http://www.process.com) and Netscape Navigator, support a variety of proxying schemes, SOCKS and transparent proxying.

Purveyor, for instance, provides proxy support for not only HTTP, but also FTP and GOPHER protocols, creating a secure LAN environment by restricting internet activities of LAN users. The proxy server offers improved performance by allowing internal proxy caching. Purveyor also provides proxy-to-proxy support for corporations with multiple proxy servers.

Tip:

For more information on Purveyor Webserver, check Process Software’s URL: http://www.process.com.

If you are running your Web server on Windows NT, Windows 95 or NetWare, you can use Purveyor Webserver’s proxy features to enhance security. In addition, you can increase the performance of your server as Purveyor can locally cache Web pages obtained from the Internet.

Installing a firewall at your site should be a must. Regardless if you are placing your server outside or inside your protected network, a firewall will be able to stop most of the attacks, but not all! The openness of HTTP is too great for you to risk. Besides, you still have all the viewers and applets to worry about.

When selecting a firewall, make sure to choose one that includes HTTP proxy server, check Appendix A "Types of Firewalls and Products on the Market" for a complete review of all the major firewalls vendors and specifications of their products. Also, check the CD that accompanies this book, as many of the vendors listed on Appendix A provided demos and evaluation copies of their products, which are worth testing.

Firewalls will tremendously help you protecting your browsers. Some firewalls, such as TIS FWTK provide HTTP proxing totally transparent to the user. More will be seeing about firewall in chapter 7, "What is an Internet/Intranet Firewall After All." For now, you must be aware of the firewalling challenges when dealing with Web security requirements and the HTTP protocol.

The Basic Web

Do you know what happens when a user connects to your site? If you don’t know how they come in, you will not know how to lock the door.

If you have a Web server on your site, every time a user establishes a connection to it, his client passes to your Web server the numeric IP address of the machine. In some wise situations, the IP address your Web server will receive is not even the client’s address, but the address of the proxy server his requests goes through. What your server will see then is the address of the proxy requesting the document on behalf of the client. But the client, thanks to the HTTP protocol, can also disclose to the Web server the username logged at the client, making the request.

Unless you have set your server to capture such information, what it will do first is to reverse the numeric IP address in an attempt to get the domain name of the client (e.g. www.vibes.com). But in order for the server to get this domain name, it must first contact a domain name server and present it with the IP address to be converted.

Many times, IP addresses cannot get reversed as they were not correctly configured. Consequently, the server cannot reverse the address. What happens next? The serve goes ahead and forges the address!

Once the Web server has the IP address and the possible domain name for the client, it start to apply a set of authentication rules, trying to determine if the client has access permission to the document requested.

Did you notice the security hole? There are few security holes here, as a result of this transaction:

As discussed above, as far as client’s threats to your server, you should be careful with the security of your server. You should make sure clients will access only what they are supposed to and if there is a hostile attack, that your server has some way to protect the access to it.

However, not all is loss, as there are few basic steps you can follow in order to enhance the security of your server:

To illustrate what a misconfigured domain name can do to a reversal IP address process, take in consideration the entries you enter in your access.conf file. Keep in mind that this file is responsible for the access control of the documents in your server.

When setting up this file, you will need to put a <directory> tag, for each directory being controlled, into the access.conf file. Within the <directory> tag you will also need to use a <limit> tag with the parameters (allow, deny, and order) needed to control access to the directory.

The following is an example where the whole Cyberspace can access the files in you top-level document directory:

<directory /usr/local/http/docs>

<limit>

order allow,deny

allow from all

</limit>

</directory>

One of the key lines here is the "order" directive, telling the server to process "allow" directives (from ALL clients) before any "deny" directives. Have you noticed we don’t have any "deny" directive?

Now lets assume you need to restrict an area on your server only for internal users to access it. Unlike the above example, you will need a "deny" directive:

<directory /usr/local/http/docscorp>

<limit>

order deny,allow

deny from all

allow from .greatplace.com

</limit>

</directory>

In this case, the "deny" directive came before the "allow" directive, so that the whole Cyberspace can have its access restricted access to the company. The "allow" directive permit access from anyone coming from greatplace.com domain.

If the server can’t reverse the IP address of a client, then you have a problem, as the domain name is critical to this process. Simply put, the user will not be able to access the Web page.

But, there it is a "Band-Aid" solution. You can add raw IP numbers to the access list.

<directory /usr/local/http/docscorp>

<limit>

order deny,allow

deny from all

allow from .greatplace.com 198.155.25

</limit>

</directory>

This way, the directive "allow" will permit any access coming from "greatplace" but also from any machine where the IP address starts with 198.155.25.

What to Watch for on the HTTP Protocol

The HTTP protocol has some more security holes to justify a firewall. One of them is that it allows remote users to request communication to a remote server machine, and to execute commands remotely. This security hole compromises the Web server and the client in many ways, including but not being limited to:

Most of these security holes are well known. Some applications like Netscape’s SSL and NCSA’s S-HTTP try to address the issue, but only partially.

The problem is that Web servers are very vulnerable to client’s behavior over the Internet. I recommend you to force Web clients to prompt a user before allowing HTTP access to reserved ports other than the port reserved for it. Otherwise, these could cause the user to unadvertedly cause a transaction to occur in a different and danger protocol.

Watch the GET and HEAD methods! The so trivial link to click an anchor to subscribe or reply to a service can trigger an applet to run without the user’s knowledge, which enables the abuse by malicious users.

Another security hole of HTTP has to do with server logs. Usually, a Web server logs a large amount of personal data about information requested by different users. Evidently, this information should remain confidential. HTTP allows the information to be retrieved without any access permission scheme.

There is a feature, the "Referer:" field, that increases the amount of personal data transferred. This field allows reading patters to be analyzed and even reverse links to be drawn. If in wrong hands, it could become a very useful and powerful tool that can lead to abuse and breach of confidentiality. To this day, there are cases where the suppression of the Referer information is not know. Developers are still working on a solution.

Many other HTTP limitations and security holes exist if we were to break down the ramifications of the above security issues presented by the protocol. Secure HTTP technologies and schemes are an attempt to address and resolve these security holes.

Taking Advantage of S-HTTP

Secure HyperText Transfer Protocol (S-HTTP) was developed to fill the gap of security in protecting sensitive information as it is transmitted over the Internet. As the need for authentication among Internet and Web grows, users need to be authenticated before sending encrypted files to each other.

S-HTTP will promote the growth of the electronic commerce as its transaction security features will promote a spontaneous commercial transactions. As S-HTTP allows Web clients and servers to be secured, the information exchanged among them will also be secured.

With S-HTTP, a secure server can reply to a request with a encrypted and signed message. By the same token, secure clients can verify a signature of a message and authenticate it. This authentication is done through the server’s private key, which is used to generate the server’s digital signatures. When the message was sent to the client, the server had delivered its public key certificate along with the signed message so that the client could verify the digital signature. The server can verify the integrity of a digitally-signed message send by a client through the same process of decrypting inbound messages from the client as well as encrypting outbound messages to the client.

You can encrypt data with shared, private or public keys. If data is encrypted with public keys, messages can be exchanged both ways and decrypted without the need for the client’s public key as the server implement a single server private key that is stored in a key database file, which is encrypted using the Webmaster’s password.

The encryption and signature is controlled through a CGI script. It is the local security configuration files and the CGI scripts S-HTTP message headers that will determine if the server will sign, encrypt, both or none.

Unfortunately, S-HTTP only works with SunOS 4.1.3, Solaris 2.4, Irix 5.2, HP-UX 9.03, DEC OSF/1, and AIX 3.2.4.

Using SSL to Enhance Security

The Secure Sockets Layer (SSL) protocol was designed and specified by Netscape Communications with the objective of improving data security layered between application protocols such as HTTP, TELNET, NNTP, FTP, and of course, TCP/IP.

SSL features data encryption, server authentication, message integrity, and optional client authentication for a TCP/IP connection.

This is an open, nonproprietary protocol, which was submitted by Netscape to the W3 Consortium for consideration as a standard security approach for Web browsers and servers. It has also been sent to the Internet Engineers Task Force (IETF) as an Internet Draft in the pursuit of having SSL standardized within the framework of the IETF.

SSL’s main goal is to promote privacy and reliability between two communicating applications. The latest version, Version 3.0 of March 1996, supersedes the earlier version from December 1995.

Still, the bases of the protocol didn’t change. It is a two layers protocol, relying, at the lowest level, on some reliable transport protocol, just like the HTTP protocol. This lower layer is called the SSL Record Protocol, which is used for encapsulation of various higher level protocols. One example is the SSL Handshake Protocol, which allows the server and the client to authenticate each other, as well as negotiate an encryption algorithm and cryptographic keys before any transmission.

The connection is private, the peer’s identity can be authenticated using asymmetric or public key, and the connection is reliable: this are the three basic properties of SSL.

The main difference between SSL and S-HTTP is that the later is a superset of the Web’s HTTP, very specific to the Web usage. The SSL protocol, however, sends messages though a socket. The whole concept of SSL can be summarized in a protocol that can secure transactions between any client and server that use the sockets layer, which involves about all the TCP/IP application.

As far as encryption goes, both SSL and S-HTTP can negotiate different types of encryption algorithms and key authentication schemes, but Netscape and Enterprise Integration Technology (EIT) both have licensed RSA Data Security’s toolkits to provide end-to-end encryption of messages, as well as key creation and certification.

Unfortunately, the future of electronic commerce and secure Web transaction can not rely in a multi-protocol security system. S-HTTP and SSL are not the same, nor work the same way. Fortunately, the Web Consortium is working hard to develop a unified security scheme that would include SSL and S-HTTP.

Moreover, these are not the only schemes been proposed. EINet’s Secure Server, which uses Kerberos and other mechanisms, and the Shen proposal, suggest more comprehensive security than SSL or S-HTTP can offer, such as extensive use of Privacy-Enhanced Mail.

Be Careful When Caching the Web!

Caching can tremendously improve the performance of your Web service by ensuring that frequently requested files will tend to be stored in the local cache. However, if the file on the remote server is updated, an out-dated file will be retrieved from the cache by the user.

Also, those files can be retrieved by a remote user, revealing information that may not be for public or external users to read.

An HTTPD server can resolved this problem by looking at the date of the file on the remote server and comparing it with the one cached. The following is a typical cache log file recorded. It provides the domain name as well as the name of the machines:

xyz_pc77.leeds.ac.uk - - [21/Nov/1994:00:43:35 +0000] "GET

http://white.nosc.mil/gif_images/NM_Sunrise_s.gif HTTP/1.0" 200 18673

xyz_pc77.leeds.ac.uk - - [21/Nov/1994:00:43:38 +0000] "GET

http://white.nosc.mil/gif_images/glacier_s.gif HTTP/1.0" 200 6474

xyz_pc77.leeds.ac.uk - - [21/Nov/1994:00:43:40 +0000] "GET

http://white.nosc.mil/gif_images/rainier_s.gif HTTP/1.0" 200 18749

In the future it may be possible to chain caches. The possibility in the long term of having institutional, metropolitan, national and continental caches are beginning to be considered.

Plugging the Holes: a Configuration Checklist

Here are few configuration checklist to help you out:

A Security Checklist

First of all, the best security checklist you can have is knowing what to check and when. The following is a list of resources on the Internet to help you keeping abreast with security issues arising everyday in Cyberspace. It can also get some free resources to help you enhance security at your site:

Novell’s HTTP: Better be Careful

Novell’s HTTP is known to have a very unsecured CGI script. If you are running a Novell Web server, you should disable the "convert.bas" CGI script it comes with.

Unfortunately, that script (the out of the box one!) allows any remote user to read any file on the remote server. How? Her it is the harmful code:

http://victim.com/scripts/convert.bas?../../anything/you/want/to/view

Novell will probably come up with a fix for this script, but as I write this chapter, to the best of my knowledge, no fixes have been provided. So make sure to disable the script when setting up you Novell HTTP!

Watch for UNIX-based Web Server Security Problems

History shows (see CERT’s reports and Bulletin Advisories) that UNIX-based Web server have tendencies to breach security at:

URI/URL

Uniform Resource Identifiers (URI), are a group of extensive technologies for naming and addressing resources such as pages, services and documents on the web. There are a number of existing addressing schemes, and more may be incorporated over time.

Figure 4.1 shows the basic structure of URI which includes:

An Uniform Resource Locator (URL) is a sort of networked extension of the standard filename concept. An URL enables you to point to a specific file on a specific directory at any giving machine attached to the Internet or Intranet. Also, this file can be served though several different methods, such as HTTP, TELNET, FTP and so forth.

The following is an overview of some of the most common URL types, as described at the National Computer Security Associations’ site at University of Illinois (http://www.ncsa.uiuc.edu/demoweb/url-primer.html).

File URLs

Suppose there is a document called "foobar.txt"; it sits on an anonymous ftp server called "ftp.yoyodyne.com" in directory "/pub/files". The URL for this file is then:

file://ftp.yoyodyne.com/pub/files/foobar.txt

The top-level directory of this FTP server is simply:

file://ftp.yoyodyne.com/

The "pub" directory of this FTP server is then:

file://ftp.yoyodyne.com/pub

Gopher URLs

Gopher URLs are a little more complicated than file URLs, since Gopher servers are a little trickier to deal with than FTP servers. To visit a particular gopher server (say, the gopher server on gopher.yoyodyne.com), use this URL:

gopher://gopher.yoyodyne.com/

Some gopher servers may reside on unusual network ports on their host machines. (The default gopher port number is 70.) If you know that the gopher server on the machine "gopher.banzai.edu" is on port 1234 instead of port 70, then the corresponding URL would be:

gopher://gopher.banzai.edu:1234/

News URLs

To point to a Usenet newsgroup (say, "rec.gardening"), the URL is simply:

news:rec.gardening

Partial URLs

Once you are viewing a document located somewhere on the network (say, the document http://www.yoyodyne.com/pub/afile.html), you can use a partial, or relative, URL to point to another file in the same directory, on the same machine, being served by the same server software. For example, if another file exists in that same directory called "anotherfile.html", then anotherfile.html is a valid partial URL at that point.

This provides an easy way to build sets of hypertext documents. If a set of hypertext documents are sitting in a common directory, they can refer to one another (i.e., be hyperlinked) by just their filenames -- however a reader got to one of the documents, a jump can be made to any other document in the same directory by merely using the other document's filename as the partial URL at that point. The additional information (access method, hostname, port number, directory name, etc.) will be assumed based on the URL used to reach the first document.

CGI

Another form of threat that makes harder for a firewall to protect a Web site involves Common Gateway Interface (CGI) scripts. Many Web pages display documents and hyperlink them to other pages or sites. However, some have search engines that will allow you to search the site (or sites) for particular information. This is done through forms that are execute by CGI scripts.

Hackers can modify these CGI script to do things it really ought not to do. Normally, these CGI scripts will only search into the Web server area, but if you modify it, it can search outside the Web server. To prevent it from happening you will need to set these scripts with low user privileges, and if you are running a UNIX-based server, make sure you search for those semicolons again.

There are many known forms of threats and many more of unknown ones. In the next sections you learn about some of the most common and threatening ones.

Further, the open architecture of Web servers allows for arbitrary Common Gateway Interface (CGI) scripts to be executed on the server’s side of the connection in response to remote requests. Any CGI script installed at your site may contain bugs, and every such bug is a potential security hole.

Caution:

Beware of CGI scripts, as they are the major source of security holes. The protocol itself is not insecure, but the scripts must be written with security in mind. If you are installing these scripts at your site, beware of the problem!

The same goes for Web server software, as more features they have greater is the potential for security holes. Servers that offer a variety of features such as CGI script execution, directory listing in real-time and script error handling, are more likely to be vulnerable to security holes. Even security tools widely used are not guaranteed to always work.

Note:

There is a Web server comparison table available at http://www.webcompare.com/. It includes freeware as well as commercial products for UNIX, Novell, Windows NT, Windows 95, VMS, and many other operating system.

For instance, right before I started writing this book, two present events come to mind. First, is about the well known Kerberos system, widely adopted for security in distributed systems, developed at MIT in the mid-1980s. The people from COAST, at Purdue University, found a vulnerability in current versions of the Kerberos. Couple students, Steve Lodin and Bryn Dole, and the professor Eugene Spafford, discovered a method where someone without privileged access to most implementations of a Kerberos 4 server could break secret session keys issued to users, allowing unauthorized access to distributed services available to a user without even knowing that user’s password. They were able to demonstrate it in a record time of less than 1 minute, on average, using a typical workstation, and sometimes as quickly as 1/5 second!

Another example is Netscape, where versions 2.0 and 2.01 were vulnerable to a "malicious" Java applet being spread over the Internet, according to a story on the New York Times of May 18. This applet, although a bit annoying, could cause denial-of-service, which potentially could cause also loss of unsaved edits in a word processor, or erratic behavior of application if you, in a verge of panic decided to reboot your machine instead of just killing your browser.

Note:

What about Java?

Java is a language developed by Sun Microsystems which allows Web pages to contain codes to be executed by browsers. The exciting thing about Java is that, by being based on a single "virtual machine" that all implementations of Java emulates, it is capable to run on any system with a version of it. There is a web browser, HotJava, totally written in the Java language. If want to learn about it, try the URL: http://java.sun.com.

However, keep in mind that denial-of-service applets are not viruses, which are created with malicious intentions. True, this Java bug had the capability to execute instruction over the Web server, remotely, with the ability even to upload information from within the remote Web server, but the security breaches that have gotten so much press were fixed in JDK 1.0.2, their current release, and in NN3.0b4.

In the interim, Netscape users were instructed to disable "Java" and "Java script" dialog box to prevent the browser from receiving such applets, or upgrade to version 2.02, which supposedly resolved the problem.

Another example you should be aware of is the existing vulnerability in the httpd servers provided by NCSA and the Apache organization. According to the Computer Incident Advisory Capability (CIAC), an user can potentially gain the same access privileges as the httpd server. This security hole not only applies to UNIX servers but to all server’s platform capable of running httpd. If you are running an NCSA httpd, you should upgrade it to version 1.5.1, its latest version.

Tip:

You can download the NCSA httpd version 1.5 from the URL ftp://ftp.ncsa.uiuc.edu/Web/httpd/UNIX/ncsa_httpd/current/httpd_1.5.1-export_source.tar.Z

Note:

If you want to download patch 1.3 for NCSA’s version 1.3 for UNIX, it is available at http://hoohoo.ncsa.uiuc.edu/.

The Apache plug-in replacement for NCSA can be found at http://www.hyperreal.com/apache/info.html).

The problem with the Apache httpd CGI is no different: a hacker could easily enter arbitrary commands on the server host using the same user-id as the user running the httpd server. If httpd is being run as root, the unauthorized commands are also run as root! Since he is using the same user-id, he can also access any file on the system that is accessible to the user-id that is running the httpd server, including but not limited to destroying file contents on the server host.

Further, if he is using an X11-based terminal emulator attached to the httpd server host, he can gain full interactive access to the server host just as if he were logging in locally.

If you are using Apache httpd, this is what you will need to do:

  1. Locate the escape_shell_command() function in the file "src/util.c" (approximately line 430). In that function, the line should read if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
  2. You will need to change that line to read if(ind("&;`'\"|*?~<>^()[]{}$\\\n",cmd[x]) != -1){
  3. Then, you will need to recompile, reinstall, and restart the server.

It is very important that you run the upgrade as if let alone, this security hole can lead to a compromise of your Web server.

Note:

For additional information you should visit CIAC’s Web page at URL: http://ciac.llnl.gov/

The same goes for CGI scripts with Novell platforms. The challenge involved with the implementation of CGI gateways on Novell-based platforms is due to the overhead involved in spawning NLMs and implementing language compilers or interpreters that reside and launch on the NetWare server. In order to resolve this problem, Great Lakes will allow data from the Web client to be either stored in a file on the NetWare server or transmitted as an MHS or SMTP E-mail message.

The NT version of both Netscape Communications Server version 1.12 and the Netscape Commerce Server, also are affected by CGI scripts handling. The following are two known problems:

Unfortunately this technique opens a major security hole on the system as it allows a remote user to execute an arbitrary set of Perl commands on the server by invoking such scripts as /cgi-bin/Perl.exe?&-e+unlink+%3C*%3E, which will cause every file in the server’s current directory to be removed.

There is another suggestion on Netscape’s technical note to encapsulate the Perl scripts in a batch (.bat) file. However, be aware that there is also a related problem with batch scripts, which makes this solution unsafe.

Both Purveyor and WebSite NT servers, because of EMWACS, use NT’s File Manager extension associations, allowing you to execute Perl scripts without having to place Perl.exe into cgi-bin. This bug does not affect these products.

"Consider test.bat:

@echo off

echo Content-type: text/plain

echo

echo Hello World!

If you try to call it as /cgi-bin/test.bat?&dir you will get the output of the CGI program, followed by a directory listing! It is like the server is executing two functions here, running the batch file test.bat and running a directory (‘DIR’ DOS Command) list, which the command interpreter is handling in the same way ‘/bin/sh’ would (run it, then, if okay, run dir command).

A possible solution for this problem would be to wrap the batch file in to a compiled executable (.exe) file. The executable file would first checks the command line parameters for things that could be misinterpreted by DOS, then invoke a command.com subshell, and run the batch file.

This would require some extra work. You probably would be better off to do everything in compiled code. Again, if you are using this version, you definitely should upgrade it. You can easily do so by accessing Netscape’s Web page at URL: http://www.netscape.com.

Also, keep in mind that there are several CGI script that allow users to change their passwords online. However, none of them have been tested enough to recommend. If you want to allow your users to change their passwords on-line, some sites have set up a second HTTP server for that sole purpose. This second server sort of replicate the password file.

Further, if you have an FTP daemon, even though generally you would not be compromising data security by sharing directories between this daemon and your Web daemon, no remote user should ever be able to upload files that can later be read or executed by your Web daemon. Otherwise, a hacker could, for example, upload a CGI script to your ftp site and then use his browser to request the newly uploaded file from your Web server, which could execute the script, totally by-passing security! Therefore, limit ftp uploads to a directory that cannot be read by any user. More about this is discussed on chapter 8, "How Vulnerable are Internet Services."

Evidently, your Web servers should support the development of application gateways, as it is essential for communicating data between an information server--in this case a Web server--and another application.

Wherever the Web server needs to communicate with another application, you will need CGI scripts to negotiate the transactions between the server and an outside application. For instance, CGIs are used to transfer data, filled in by a user in an HTML form, from the Web server to a database.

But if you want to preserve the security of your site, and you must, be alert about allowing your users to run their own CGI scripts. These scripts are very powerful, which could represent some risks for your site. As discussed earlier, CGI scripts, if poorly written could open security roles in your system. Thus, never run your Web server as root; make sure it is configured to change to another user ID at startup time. Also, consider using a CGI wrapper to ensure the scripts run with the permissions and user id of the author. You can easily download one from URL: http//www.umr.edu/~cgiwrap

Tip:

You should check the URL: URL: http://www.primus.com/staff/paulp/cgi-security/ for security related scripts.

CGI are not all bad! A good security tool to control who is accessing your Web server is to actually use CGI scripts to identify them. There are five very important environment variables available to help you do that:

  1. HTTP_FROM - This variable is usually set to the email address of the user. You should use it as a default for the reply email address in an email form.
  2. REMOTE_USER - It is only set if secure authentication was used to access the script. You can use the AUTH_TYPE variable to check what form of secure authentication was used. REMOTE_USER will display the name of the user authenticated under.
  3. REMOTE_IDENT - It is set if the server has contacted an IDENTD server on the browser machine. However, there is no way to ensure a honest reply from the browser
  4. REMOTE_HOST - Provides information about the site the user is connecting from if the hostname was retrieved by the server.
  5. REMOTE_ADDR - This also provides information about the site the user is connecting from. It will provide the dotted-decimal IP address of the user.
Caution:

If you ever suspect your site have been broken-in you should contact the Computer Emergency Response Team (CERT). CERT was formed by the Defense Advanced Research Projects Agency (DARPA) in 1988 to serve as a focal point for the computer security concerns of Internet users. The Software Engineering at Carnegie Mellon University, in Pittsburgh, PA runs the Coordination Center for the CERT. You can visit their Web page at URL: http://www.cert.org or send an e-mail to cert@cert.org.

Also, CGI can be used to create e-mail forms on the Web. There is a CGI e-mail form, developed in Perl by Doug Stevenson (doug+@osu.edu), of Ohio State University, that is fairly secure. The script, called "Web Mailto Gateway," enables you to hide the real e-mail addresses from user, which helps to enhance security. The following source code can be found at URL: http://www.mps.ohio-state.edu/mailto/mailto_info.html.

#!/usr/local/bin/perl

#

# Doug's WWW Mail Gateway 2.2

# 5/95

# All material here is Copyright 1995 Doug Stevenson.

#

# Use this script as a front end to mail in your HTML. Not every browser

# supports the mailto: URLs, so this is the next best thing. If you

# use this script, please leave credits to myself intact! :) You can

# modify it all you want, though.

#

# Documentation at:

# http://www-bprc.mps.ohio-state.edu/mailto/mailto_info.html

#

# Configurable items are just below. Also pay special attention to

# GET method arguments that this script accepts to specify defaults

# for some fields.

#

# I didn't exactly follow the RFCs on mail headers when I wrote this,

# so please send all flames my way if it breaks your mail client!!

# Also, you'll need cgi-lib.pl for the GET and POST parsing. I use

# version 1.7.

#

# Requires cgi-lib.pl which can be found at

# http://www.bio.cam.ac.uk/web/form.html

#

# PLEASE: Use this script freely, but leave credits to myself!! It's

# common decency!

#

########

#

# Changes from 1.1 to 1.2:

#

# A common modification to the script for others to make was to allow

# only a certain few mail addresses to be sent to. I changed the WWW

# Mail Gateway to allow only those mail addresses in the list @addrs

# to be mailed to - they are placed in a HTML <SELECT> list, with either

# the selected option being either the first one or the one that matches

# the "to" CGI variable. Thanks to Mathias Koerber

# <Mathias.Koerber@swi.com.sg> for this suggestion.

#

# Also made one minor fix.

#

########

#

# Changes from 1.2 to 1.3:

#

# Enhancing the enhancements from 1.2. You can now specify a real name

# or some kind of identifier to go with the real mail address. This

# infomation gets put in the %addrs associative array, either explicitly

# defined, or read from a file. Read the information HTML for instructions

# on how to set this up. Also, real mail addresses may hidden from the

# user. Undefine or set to zero the variable $expose_address below.

#

########

#

# Changes from 1.3 to 1.4

#

# The next URL to be fetched after the mail is sent can be specified with

# the cgi varaible 'nexturl'.

#

# Fixed some stupid HTML mistake.

#

# Force user to enter something for the username on 'Your Email:' tag,

# if identd didn't get a username.

#

# Added Cc: field, only when %addrs is not being used.

#

########

#

# Quickie patch to 1.41

#

# Added <PRE>formatted part to header entry to make it look nice and fixed a

# typo.

#

########

#

# Version 2.0 changes

#

# ALL cgi varaibles (except those reserved for mail info) are logged

# at then end of the mail received. You can put forms, hidden data,

# or whatever you want, and the info for each variable will get logged.

#

# Cleaned up a lot of spare code.

#

# IP addresses are now correctly logged instead of just hostnames.

#

# Made source retrieval optional.

#

########

#

# Changes from 2.0 to 2.1

#

# Fixed stupid HTML error for an obscure case. Probably never noticed.

#

# Reported keys are no longer reported in an apparently random order; they

# are listed in the order they were received. That was a function of perl

# hashes...changed to a list operation instead.

#

########

#

# Changes from 2.1 to 2.2

#

# Added all kinds of robust error checking and reporting. Should be

# easier to diagnose problems from the user end.

#

# New suggested sendmail flag -oi to keep sendmail from ending mail

# input on line containing . only.

#

# Added support for setting the "real" From address in the first line

# of the mail header using the -f sendmail switch. This may or may not

# be what you want, depending on the application of the script. This is

# useful for listservers that use that information for identification

# purposes or whatever. This is NOT useful if you're concerned about

# the security of your script for public usage. Your mileage will vary,

# please read the sendmail manual about the -f switch.

# Thanks to Jeff Lawrence (jlaw@irus.rri.uwo.ca) for figuring this

# one out.

#

########

#

# Doug Stevenson

# doug+@osu.edu

######################

# Configurable options

######################

# whether or not to actually allow mail to be sent -- for testing purposes

$active = 1;

# Logging flag. Logs on POST method when mail is sent.

$logging = 1;

$logfile = '/usr/local/WWW/etc/mailto_log';

# Physical script location. Define ONLY if you wish to make your version

# of this source code available with GET method and the suffix '?source'

# on the url.

$script_loc = '/usr/local/WWW/cgi-bin/mailto.pl';

# physical location of your cgi-lib.pl

$cgi_lib = '/usr/local/WWW/cgi-bin/cgi-lib.pl';

# http script location

$script_http = 'http://www-bprc.mps.ohio-state.edu/cgi-bin/mailto.pl';

# Path to sendmail and its flags. Use the first commented version and

# define $listserver = 1if you want the gateway to be used for listserver

# subscriptions -- the -f switch might be neccesary to get this to work

# correctly.

#

# sendmail options:

# -n no aliasing

# -t read message for "To:"

# -oi don't terminate message on line containing '.' alone

#$sendmail = "/usr/lib/sendmail -t -n -oi -f"; $listserver = 1;

$sendmail = "/usr/lib/sendmail -t -n -oi";

# set to 1 if you want the real addresses to be exposed from %addrs

#$expose_address = 1;

# Uncomment one of the below chunks of code to implement restricted mail

# List of address to allow ONLY - gets put in a HTML SELECT type menu.

#

#%addrs = ("Doug - main address", "doug+@osu.edu",

# "Doug at BPRC", "doug@polarmet1.mps.ohio-state.edu",

# "Doug at CIS", "stevenso@cis.ohio-state.edu",

# "Doug at the calc lab", "dstevens@mathserver.mps.ohio-state.edu",

# "Doug at Magnus", "dmsteven@magnus.acs.ohio-state.edu");

# If you don't want the actual mail addresses to be visible by people

# who view source, or you don't want to mess with the source, read them

# from $mailto_addrs:

#

#$mailto_addrs = '/usr/local/WWW/etc/mailto_addrs';

#open(ADDRS,$mailto_addrs);

#while(<ADDRS>) {

# ($name,$address) = /^(.+)[ \t]+([^ ]+)\n$/;

# $name =~ s/[ \t]*$//;

# $addrs{$name} = $address;

#}

# version

$version = '2.2';

#############################

# end of configurable options

#############################

##########################

# source is self-contained

##########################

if ($ENV{'QUERY_STRING'} eq 'source' && defined($script_loc)) {

print "Content-Type: text/plain\n\n";

open(SOURCE, $script_loc) ||

&InternalError('Could not open file containing source code');

print <SOURCE>;

close(SOURCE);

exit(0);

}

require $cgi_lib;

&ReadParse();

#########################################################################

# method GET implies that we want to be given a FORM to fill out for mail

#########################################################################

if ($ENV{'REQUEST_METHOD'} eq 'GET') {

# try to get as much info as possible for fields

# To: comes from $in{'to'}

# Cc: comes from $in{'cc'}

# From: comes from REMOTE_IDENT@REMOTE_HOST || $in{'from'} || REMOTE_USER

# Subject: comes from $in{'sub'}

# body comes from $in{'body'}

$destaddr = $in{'to'};

$cc = $in{'cc'};

$subject = $in{'sub'};

$body = $in{'body'};

$nexturl = $in{'nexturl'};

if ($in{'from'}) {

$fromaddr = $in{'from'};

}

# this is for NetScape pre-1.0 beta users - probably obsolete code

elsif ($ENV{'REMOTE_USER'}) {

$fromaddr = $ENV{'REMOTE_USER'};

}

# this is for Lynx users, or any HTTP/1.0 client giving From header info

elsif ($ENV{'HTTP_FROM'}) {

$fromaddr = $ENV{'HTTP_FROM'};

}

# if all else fails, make a guess

else {

$fromaddr = "$ENV{'REMOTE_IDENT'}\@$ENV{'REMOTE_HOST'}";

}

# Convert multiple bodies (separated by \0 according to CGI spec)

# into one big body

$body =~ s/\0//;

# Make a list of authorized addresses if %addrs exists.

if (%addrs) {

$selections = '<SELECT NAME="to">';

foreach (sort keys %addrs) {

if ($in{'to'} eq $addrs{$_}) {

$selections .= "<OPTION SELECTED>$_";

}

else {

$selections .= "<OPTION>$_";

}

if ($expose_address) {

$selections .= " &lt;$addrs{$_}>";

}

}

$selections .= "</SELECT>\n";

}

# give them the form

print &PrintHeader();

print <<EOH;

<HTML><HEAD><TITLE>Doug\'s WWW Mail Gateway $version</TITLE></HEAD>

<BODY><H1><IMG SRC="http://www-bprc.mps.ohio-state.edu/pics/mail2.gif" ALT="">

The WWW Mail Gateway $version</H1>

<P>The <B>To</B>: field should contain the <B>full</B> Email address

that you want to mail to. The <B>Your Email</B>: field needs to

contain your mail address so replies go to the right place. Type your

message into the text area below. If the <B>To</B>: field is invalid,

or the mail bounces for some reason, you will receive notification

if <B>Your Email</B>: is set correctly. <I>If <B>Your Email</B>:

is set incorrectly, all bounced mail will be sent to the bit bucket.</I></P>

<FORM ACTION="$script_http" METHOD=POST>

EOH

;

print "<P><PRE> <B>To</B>: ";

# give the selections if set, or INPUT if not

if ($selections) {

print $selections;

}

else {

print "<INPUT VALUE=\"$destaddr\" SIZE=40 NAME=\"to\">\n";

print " <B>Cc</B>: <INPUT VALUE=\"$cc\" SIZE=40 NAME=\"cc\">\n";

}

print <<EOH;

<B>Your Name</B>: <INPUT VALUE="$fromname" SIZE=40 NAME="name">

<B>Your Email</B>: <INPUT VALUE="$fromaddr" SIZE=40 NAME="from">

<B>Subject</B>: <INPUT VALUE="$subject" SIZE=40 NAME="sub"></PRE>

<INPUT TYPE="submit" VALUE="Send the mail">

<INPUT TYPE="reset" VALUE="Start over"><BR>

<TEXTAREA ROWS=20 COLS=60 NAME="body">$body</TEXTAREA><BR>

<INPUT TYPE="submit" VALUE="Send the mail">

<INPUT TYPE="reset" VALUE="Start over"><BR>

<INPUT TYPE="hidden" NAME="nexturl" VALUE="$nexturl"></P>

</FORM>

<HR>

<H2>Information about the WWW Mail Gateway</H2>

<H3><A HREF="http://www-bprc.mps.ohio-state.edu/mailto/mailto_info.html#about">

About the WWW Mail Gateway</A></H3>

<H3><A HREF="http://www-bprc.mps.ohio-state.edu/mailto/mailto_info.html#new">

New in version $version</A></H3>

<H3><A HREF="http://www-bprc.mps.ohio-state.edu/mailto/mailto_info.html#misuse">

Please report misuse!</A></H3>

<HR>

<ADDRESS><P><A HREF="/~doug/">Doug Stevenson: doug+\@osu.edu</A>

</P></ADDRESS>

</BODY></HTML>

EOH

;

}

#########################################################################

# Method POST implies that they already filled out the form and submitted

# it, and now it is to be processed.

#########################################################################

elsif ($ENV{'REQUEST_METHOD'} eq 'POST') {

# get all the variables in their respective places

$destaddr = $in{'to'};

$cc = $in{'cc'};

$fromaddr = $in{'from'};

$fromname = $in{'name'};

$replyto = $in{'from'};

$sender = $in{'from'};

$errorsto = $in{'from'};

$subject = $in{'sub'};

$body = $in{'body'};

$nexturl = $in{'nexturl'};

$realfrom = $ENV{'REMOTE_HOST'} ? $ENV{'REMOTE_HOST'}: $ENV{'REMOTE_ADDR'};

# check to see if required inputs were filled - error if not

unless ($destaddr && $fromaddr && $body && ($fromaddr =~ /^.+\@.+/)) {

print <<EOH;

Content-type: text/html

Status: 400 Bad Request

<HTML><HEAD><TITLE>Mailto error</TITLE></HEAD>

<BODY><H1>Mailto error</H1>

<P>One or more of the following necessary pieces of information was missing

from your mail submission:

<UL>

<LI><B>To</B>:, the full mail address you wish to send mail to</LI>

<LI><B>Your Email</B>: your full email address</LI>

<LI><B>Body</B>: the text you wish to send</LI>

</UL>

Please go back and fill in the missing information.</P></BODY></HTML>

EOH

exit(0);

}

# do some quick logging - you may opt to have more/different info written

if ($logging) {

open(MAILLOG,">>$logfile");

print MAILLOG "$realfrom\n";

close(MAILLOG);

}

# Log every CGI variable except for the ones reserved for mail info.

# Valid vars go into @data. Text output goes into $data and gets.

# appended to the end of the mail.

# First, get an ORDERED list of all cgi vars from @in to @keys

for (0 .. $#in) {

local($key) = split(/=/,$in[$_],2);

$key =~ s/\+/ /g;

$key =~ s/%(..)/pack("c",hex($1))/ge;

push(@keys,$key);

}

# Now weed out the ones we want

@reserved = ('to', 'cc', 'from', 'name', 'sub', 'body', 'nexturl');

local(%mark);

foreach (@reserved) { $mark{$_} = 1; }

@data = grep(!$mark{$_}, @keys);

foreach (@data) {

$data .= "$_ -> $in{$_}\n";

}

# Convert multiple bodies (separated by \0 according to CGI spec)

# into one big body

$body =~ s/\0//;

# now check to see if some joker changed the HTML to allow other

# mail addresses besides the ones in %addrs, if applicable

if (%addrs) {

if (!scalar(grep($_." <$addrs{$_}>" eq $destaddr ||

$destaddr eq $_, keys(%addrs)))) {

print &PrintHeader();

print <<EOH;

<HTML><HEAD><TITLE>WWW Mail Gateway: Mail address not allowed</TITLE></HEAD>

<BODY>

<H1>Mail address not allowed</H1>

<P>The mail address you managed to submit, <B>$destaddr</B>, to this script is

not one of the pre-defined set of addresses that are allowed. Go back and

try again.</P>

</BODY></HTML>

EOH

;

exit(0);

}

}

# if we just received an alias, then convert that to an address

$realaddr = $destaddr;

if ($addrs{$destaddr}) {

$realaddr = "$destaddr <$addrs{$destaddr}>";

}

# fork over the mail to sendmail and be done with it

if ($active) {

if ($listserver) {

open(MAIL,"| $sendmail$fromaddr") ||

&InternalError('Could not fork sendmail with -f switch');

}

else {

open(MAIL,"| $sendmail") ||

&InternalError('Could not fork sendmail with -f switch');

}

# only print Cc if we got one

print MAIL "Cc: $cc\n" if $cc;

print MAIL <<EOM;

From: $fromname <$fromaddr>

To: $realaddr

Reply-To: $replyto

Errors-To: $errorsto

Sender: $sender

Subject: $subject

X-Mail-Gateway: Doug\'s WWW Mail Gateway $version

X-Real-Host-From: $realfrom

$body

$data

EOM

close(MAIL);

}

# give some short confirmation results

#

# if the cgi var 'nexturl' is given, give out the location, and let

# the browser do the work.

if ($nexturl) {

print "Location: $nexturl\n\n";

}

# otherwise, give them the standard form.

else {

print &PrintHeader();

print <<EOH;

<HTML><HEAD><TITLE>Mailto results</TITLE></HEAD>

<BODY><H1>Mailto results</H1>

<P>Mail sent to <B>$destaddr</B>:<BR><BR></P>

<PRE>

<B>Subject</B>: $subject

<B>From</B>: $fromname &lt;$fromaddr>

$body</PRE>

<HR>

<A HREF="$script_http">Back to the WWW Mailto Gateway</A>

</BODY></HTML>

EOH

;

}

} # end if METHOD=POST

#####################################

# What the heck are we doing here????

#####################################

else {

print <<EOH;

<HTML><HEAD><TITLE>Mailto Gateway error</TITLE></HEAD>

<BODY><H1>Mailto Gateway error</H1>

<P>Somehow your browser generated a non POST/GET request method and it

got here. You should get this fixed!!</P></BODY></HTML>

EOH

}

exit(0);

#

# Deal out error messages to the user. Gets passed a string containing

# a description of the error

#

sub InternalError {

local($errmsg) = @_;

print &PrintHeader();

print <<EOH;

Content-type: text/html

Status: 502 Bad Gateway

<HTML><HEAD><TITLE>Mailto Gateway Internal Error</TITLE></HEAD>

<BODY><H1>Mailto Gateway Internal Error</H1>

<P>Your mail failed to send for the following reason:<BR><BR>

<B>$errmesg</B></P></BODY></HTML>

EOH

exit(0);

}

##

## end of mailto.pl

##

If your server can run CGI scripts and is configured with sendmail, this is the right, and secure, mail gateway script to have in your HTML, you will need to be able to run CGI scripts on your server though.

Orders Orders Backward Forward
Comments Comments

COMPUTING MCGRAW-HILL | Beta Books | Contact Us | Order Information | Online Catalog


HTML conversions by Mega Space.

This page updated on December 05, 1997 by Webmaster.

Computing McGraw-Hill is an imprint of the McGraw-Hill Professional Book Group.

Copyright ©1997 The McGraw-Hill Companies, Inc. All Rights Reserved.
Any use is subject to the rules stated in the Terms of Use.