Bugtraq mailing list archives
PHP/FI command line buffer overflow
From: davids () SECNET COM (David Sacerdote)
Date: Thu, 17 Apr 1997 16:02:07 -0600
-----BEGIN PGP SIGNED MESSAGE----- ###### ## ## ###### ## ### ## ## ###### ## # ## ## ## ## ### ## ###### . ## ## . ######. Secure Networks Inc. Security Advisory April 17, 1997 Buffer Overflow in php.cgi This advisory describes a remotely exploitable buffer overflow in the PHP cgi program. This is *NOT* the PATTERN_RESTRICT issue described in earlier bugtraq discussion. Problem Description ~~~~~~~~~~~~~~~~~~~ In the function FixFilename() function in file.c, PHP attempts to pass strings whose length may be as long as 8 kilobytes into buffers as small as 128 bytes. This overwrites the stack, making it possible for an attacker to obtain shell access to the machine running the web server. Technical Details ~~~~~~~~~~~~~~~~~ The filename argument to FixFilename is derived from the command line used to invoke to the CGI script, or from the QUERY_STRING environment variable passed to it. The total length of either can be as long as eight kilobytes, but the fn string is a mere 128 bytes long. An excerpt from the flawed code reads: char *FixFilename(char *filename, int cd, int *ret) { ... char fn[128], user[128], *s; ... s = strrchr(filename,'/'); if(s) { strcpy(fn,s+1); ... Impact ~~~~~~ Attackers can remotely obtain shell or command line access to any vulnerable system. Vulnerable Systems ~~~~~~~~~~~~~~~~~~ Any computer running a web server with php.cgi 2.0beta10 or earlier is vulnerable, irrespective of what operating system it is running, provided that PHP is run as a cgi, and not as an Apache module. When compiled as an Apache module, PHP does not appear to execute the problem code. To determine whether a system is running a web server with php.cgi installed as a cgi, use your favorite web browser to access the URL http://hostname/cgi-bin/php.cgi If you see something like: PHP/FI Version 2.0b10 ... Then the machine hostname is running PHP/FI. Fix information ~~~~~~~~~~~~~~~ Use the patch program to apply the following diffs to file.c, then recompile php.cgi. These diffs are against version 2.0b10. *** file.c Thu Apr 17 09:36:07 1997 - --- file.c.fixed Thu Apr 17 09:36:00 1997 *************** *** 295,315 **** s = strrchr(filename,'/'); if(s) { ! strcpy(fn,s+1); o=*s; *s='\0'; ! strcpy(path,filename); *s=o; } else { #ifdef PHP_ROOT_DIR ! strcpy(path,PHP_ROOT_DIR); #else path[0] = '\0'; #endif ! strcpy(fn,filename); } if(fn && *fn=='~') { ! strcpy(path,fn); fn[0]='\0'; } if(*path) { - --- 295,320 ---- s = strrchr(filename,'/'); if(s) { ! strncpy(fn,s+1, sizeof (fn)); ! fn[sizeof(fn) - 1] = '\0'; o=*s; *s='\0'; ! strncpy(path,filename, sizeof (path)); ! path[sizeof(path) - 1] = '\0'; *s=o; } else { #ifdef PHP_ROOT_DIR ! strncpy(path,PHP_ROOT_DIR, sizeof(path)); ! path[sizeof(path) -1] = '\0'; #else path[0] = '\0'; #endif ! strncpy(fn,filename, sizeof (fn)); ! fn[sizeof(fn) - 1] = '\0'; } if(fn && *fn=='~') { ! strncpy(path,fn, sizeof (path)); ! path[sizeof(path) - 1] = '\0'; fn[0]='\0'; } if(*path) { *************** *** 319,328 **** o=*s; *s='\0'; } ! strcpy(user,path+1); if(s) { *s=o; ! strcpy(temp,s); } else temp[0]='\0'; #ifdef HAVE_PWD_H if(*user) { - --- 324,335 ---- o=*s; *s='\0'; } ! strncpy(user,path+1, sizeof (user)); ! user[sizeof(user) - 1] = '\0'; if(s) { *s=o; ! strncpy(temp,s, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; } else temp[0]='\0'; #ifdef HAVE_PWD_H if(*user) { *************** *** 333,339 **** pd = getenv(PHP_PUB_DIRNAME_ENV); #endif if (pd == 0) pd = PHP_PUB_DIRNAME; ! sprintf(path,"%s/%s%s",pw->pw_dir,pd,temp); } } #endif - --- 340,351 ---- pd = getenv(PHP_PUB_DIRNAME_ENV); #endif if (pd == 0) pd = PHP_PUB_DIRNAME; ! strcpy (path,pw->pw_dir); ! strcat (path,"/"); ! strncat (path, pd, ! sizeof(path) - strlen(path) - 1); ! strncat (path, temp, ! sizeof (path) - strlen(path) - 1); } } #endif *************** *** 343,352 **** o=*s; *s='\0'; } ! strcpy(user,path+2); if(s) { *s=o; ! strcpy(temp,s); } else temp[0]='\0'; #if HAVE_PWD_H if(*user) { - --- 355,366 ---- o=*s; *s='\0'; } ! strncpy(user,path+2, sizeof (user)); ! user[sizeof(user) - 1] = '\0'; if(s) { *s=o; ! strncpy(temp,s,sizeof(temp)); ! temp[sizeof(temp) - 1] = '\0'; } else temp[0]='\0'; #if HAVE_PWD_H if(*user) { *************** *** 357,363 **** pd = getenv(PHP_PUB_DIRNAME_ENV); #endif if (pd == 0) pd = PHP_PUB_DIRNAME; ! sprintf(path,"%s/%s%s",pw->pw_dir,pd,temp); } } #endif } - --- 371,383 ---- pd = getenv(PHP_PUB_DIRNAME_ENV); #endif if (pd == 0) pd = PHP_PUB_DIRNAME; ! strcpy (path,pw->pw_dir); ! strcat (path,"/"); ! strncat (path, pd, ! sizeof(path) - strlen(path) - 1); ! strncat (path, temp, ! sizeof (path) - strlen(path) - 1); ! } } #endif } *************** *** 370,376 **** } } if(*fn) { ! sprintf(temp,"%s/%s",path,fn); #ifndef WINDOWS st = stat(temp,&gsb); #else - --- 390,399 ---- } } if(*fn) { ! strncpy (temp, path, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strcat (temp,"/"); ! strncat(temp,fn,sizeof(temp) - strlen(temp) - 1); #ifndef WINDOWS st = stat(temp,&gsb); #else *************** *** 382,394 **** st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! sprintf(temp,"%s/%s/index.html",path,fn); st = stat(temp,&gsb); if(st==-1) { ! sprintf(temp,"%s/%s/index.phtml",path,fn); st = stat(temp,&gsb); } ! sprintf(path,"%s/%s",path,fn); } else if(st==-1) { l = strlen(temp); if(strlen(fn)>4) { - --- 405,431 ---- st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! strncpy (temp,path,sizeof(temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strcat (temp, "/"); ! strncat (temp,fn, ! sizeof(temp) - strlen (temp) - 1); ! strncat (temp,"/index.html", ! sizeof(temp) - strlen (temp) - 1); st = stat(temp,&gsb); if(st==-1) { ! strncpy (temp,path,sizeof(temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strcat (temp, "/"); ! strncat (temp,fn, ! sizeof(temp) - strlen (temp) - 1); ! strncat (temp,"/index.html", ! sizeof(temp) - strlen (temp) - 1); st = stat(temp,&gsb); } ! strcat (path,"/"); ! strncat (path, fn, ! sizeof(path) - strlen(path) - 1); } else if(st==-1) { l = strlen(temp); if(strlen(fn)>4) { *************** *** 410,422 **** st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! sprintf(temp,"%s/index.html",path); st = stat(temp,&gsb); if(st==-1) { ! sprintf(temp,"%s/index.phtml",path); st = stat(temp,&gsb); } ! } else strcpy(temp,path); } } else { #ifndef WINDOWS - --- 447,468 ---- st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! strncpy (temp, path, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strncat (temp, "/index.html", ! sizeof (temp) - strlen (temp) - 1); st = stat(temp,&gsb); if(st==-1) { ! strncpy (temp, path, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strncat (temp, "/index.phtml", ! sizeof (temp) - strlen (temp) - 1); st = stat(temp,&gsb); } ! } else { ! strncpy(temp,path, sizeof (temp)); ! temp[sizeof (temp) - 1] = '\0'; ! } } } else { #ifndef WINDOWS *************** *** 430,442 **** st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! sprintf(temp,"%s/index.html",fn); st = stat(temp,&gsb); if(st==-1) { ! sprintf(temp,"%s/index.phtml",fn); st = stat(temp,&gsb); } ! } else strcpy(temp,fn); } *ret=st; return(temp); - --- 476,498 ---- st = -1; #endif if((st!=-1) && (gsb.st_mode&S_IFMT)==S_IFDIR) { ! strncpy (temp, fn, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strncat (temp, "/index.html", ! sizeof (temp) - strlen (temp) - 1); st = stat(temp,&gsb); if(st==-1) { ! strncpy (temp, fn, sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! strncat (temp, "/index..phtml", ! sizeof (temp) - strlen (temp) - 1); ! st = stat(temp,&gsb); } ! } else { ! strncpy(temp,fn,sizeof (temp)); ! temp[sizeof(temp) - 1] = '\0'; ! } } *ret=st; return(temp); Additional Information ~~~~~~~~~~~~~~~~~~~~~~ If you have any questions about this advisory, feel free to mail me at davids () secnet com. Past Secure Networks advisories can be found at ftp://ftp.secnet.com/pub/advisories, and Secure Networks papers can be found at ftp://ftp.secnet.com/pub/papers. PHP/FI was written by Rasmus Lerdorf <rasmus () vex net>. Additional information about PHP/FI can be found at http://www.vex.net/php This advisory does NOT address a recently published hole in the php.cgi which allows attackers to obtain copies of any file on the web server which is readable by the user the php.cgi program runs as. FIRST and vendor contacts please note that this advisory was expedited. This is becuase we felt that previous public post (by another) party would lead to the eventual discovery of this bug. As a result of this we therefore wanted a fix to be availible to the public as soon as possible. The following PGP key is for davids () secnet com, should you wish to encrypt any message traffic to the author of this advisory: - -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.2 mQCNAzJ4qJAAAAEEAOgB7mooQ6NgzcUSIehKUufGsyojutC7phVXZ+p8FnHLLZNB BLQEtj5kmfww2A2pR29q4rgPeqEUOjWPlLNdSLby3NI8yKz1AQSQLHAwIDXt/lku 8QXClaV6pNIaQSN8cnyyvjH6TYF778yZhYz0mwLqW6dU5whHtP93ojDw1UhtAAUR tCtEYXZpZCBTYWNlcmRvdGUgPGRhdmlkc0BzaWxlbmNlLnNlY25ldC5jb20+ =LtL9 - -----END PGP PUBLIC KEY BLOCK----- Feel free to send responses and commments to sni () secnet com. If you should wish to encrypt such traffic, please use the Secure Networks Inc. key: - -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.2 mQCNAzLaFzIAAAEEAKsVzPR7Y6oFN5VPE/Rp6Sm82oE0y6Mkuof8QzERV6taihn5 uySb31UeNJ4l6Ud9alOPT/0YdeOO9on6eD1iU8qumFxzO3TLm8nTAdZehQSAQfoa rWmpwj7KpXN/3n+VyBWvhpBdKxe08SQN4ZjvV5HXy4YIrE5bTbgIhFKeVQANAAUR tCVTZWN1cmUgTmV0d29ya3MgSW5jLiA8c25pQHNlY25ldC5jb20+iQCVAwUQM03n 27Tl3s+VYMi5AQHdGwP+N3hhILzzhSvhx1gj6ZElgsLa7Q1P3cTlc/Xqx50/wkcX qIwiPudH+9UHvpL8fUNaHc9iZf3y8YZz0HWz56Vm5SG7uBfB/ksq4x04pQ65dQ1m v51DYCvLG9u0jL4hC3Mz9WvIMANXqOUlAhuU1iy0wM41joE8aHdh2jsLHlB5qlSJ AJUDBRAzTlbK/3eiMPDVSG0BAcTNA/9eF0X4Ei8LM4CXFW7JTB5vwXxerR6FmKI8 0JXt6KTrjGBzTfBrDGUZHNakPELjQPQI+fqg6hKJ7Ro1eSL4QbtX2BTO+wIWoLJG hQmccKleuEK5N9vFgzvPTRknfkbqL1Ta7g3Z9tE8TQhFbj0x4yNFAPB/hOhVvY3s YOkUx4T12A== =ljNl - -----END PGP PUBLIC KEY BLOCK----- Copyright Notice ~~~~~~~~~~~~~~~~ The contents of this advisory are Copyright (C) 1997 Secure Networks Inc, and may be distributed freely provided that no fee is charged for distribution, and that proper credit is given. PHP sources distributed as part of this advisory fall under the GNU Public license, version 2. -----BEGIN PGP SIGNATURE----- Version: 2.6.2 iQCVAwUBM1ZjwbgIhFKeVQANAQE/HQP/cuvfviM3RdAtMFw4JlafVfAZ8KNYaP61 dHcg0KmEZYeChOFgtRULHj9d2bhYniAjwVkioO4vIwvsmfNZSGnP3kMMQRv0oSkJ 9MNqeupqeF3cs3i88m8bT8TH9qNOvsbHAGix/TNHvgSK63rzUfzbfDbId8YwA2JD 2892qweY4b0= =vuDt -----END PGP SIGNATURE-----
Current thread:
- TcpWrappers and Sendmail, (continued)
- TcpWrappers and Sendmail Neil Harkins (Apr 15)
- Handy change I made in ltread.c Nathan D. Faber (Apr 15)
- NIS+ and signed directory objects Sun Security Coordination (Apr 15)
- Update on PHP/FI hole Shamanski (Apr 16)
- Buffer overflow in sperl5.003 Murphy (Apr 17)
- Re: Buffer overflow in sperl5.003 David Luyer (Apr 17)
- Re: Buffer overflow in sperl5.003 Jon Lewis (Apr 19)
- [NTSEC] ALERT - NT security flaw announcement Aleph One (Apr 18)
- Beta testers wanted for new security tool! Alfred Huger (Apr 18)
- IRIX 6.x /cgi-bin/wrap bug J.A. Gutierrez (Apr 19)
- Re: Buffer overflow in sperl5.003 David Luyer (Apr 17)
- PHP/FI command line buffer overflow David Sacerdote (Apr 17)
- Sun Security Bulletin #00138 Aleph One (Apr 17)