From: owner-wu-ftpd@wugate.wustl.edu [mailto:owner-wu-ftpd@wugate.wustl. edu] On Behalf Of Gregory A Lundberg Sent: Tuesday, March 23, 1999 10:44 AM To: Russ Allbery Cc: ayu1@nycap.rr.com; wu-ftpd@wugate.wustl.edu Subject: Re: FW: ftp exploit > > On 23 Mar 1999, Russ Allbery wrote: > > > any comments? > > It's an exploit script for the path overflow bug that's already been > announced by CERT, been on all the security lists, and has already > been fixed in the latest version of every wu-ftpd variant that I'm > aware of as well as being the impetus for the final mainline wu-ftpd > release? > Correct. This is a full exploit against Redhat 5.2 (the original advisory was based upon a test, not an exploit). > My comment: This posting proves why you need to keep up with the CERT mailing list, if not Bugtraq and other lists. As often heppens, the exploit followed the discovery of the vulnerability by several weeks. While it sometimes happens that exploits are distributed before the daemon authors are notified and public security announcement made, this was not the case here. > > > My testing shows: > This is an exploit using the buffer overflow described in > CERT Advisory CA-99.03 - FTP-Buffer-Overflows > Available from htp://www.CERT.org/ > It is directed solely at Redhat CD 4.2 Linux systems running a clean, default install. It was not successfull on unclean 5.2 systems, the pre-5.2 systems I tested on, or when I built the daemon by-hand instead of using a Redhat (S)RPM. My testing showed, while none of the systems I have available were exploitable, the exploit WOULD HAVE WORKED but failed for identifiable reasons. > Given working code for Redhat 4.2, it should be a fairly simply matter to port to non-Linux or non-5.2 systems. > > > WHO IS VULNERABLE ----------------- > - Systems running ALL versions of WU-FTPD _prior_ to 2.4.2 (final), including all 2.4.2-beta versions, ARE VULNERABLE, except as noted below: > - Systems with proper upload clauses are partially protected. Many systems do not use proper upload clauses for real/guest users and are NOT protected from abuse by their local users. > - Systems with proper permissions are partially protected. Most systems do not use proper permissions for real/guest users since they would prevent use by Telnet/SSH/Shell .. such systems are NOT protected from their local users. > > > WHO IS NOT VULNERABLE --------------------- > - Systems running 2.4.2 (final) are protected against _this_ bug. Such systems should upgrade to VR16 for maximum security; a number of other bugs and security problems have been fixed in VR16. > - Systems running 2.4.2-beta-18-VR10 or later are protected. Anyone running VR10 through VR13 should upgrade to VR14 or later at your earliest convenience. > - Systems running BeroFTPD 1.2.0 or later are NOT vulnerable. All BeroFTPD systems should upgrade to the current version (1.3.4) at their earliest conenience. Anyone running a vulnerable system with NEWVIRT, will want to immedeately upgrade to BeroFTPD. > > > The location of the latest version of wu-ftpd can be found in the directory > ftp://ftp.vr.net/pub/wu-ftpd/ > >wu-ftpd Resource Center: http://www.landfield.com/wu-ftpd/ >wu-ftpd FAQ: http://www.cetis.hvu.nl/~koos/wu-ftpd-faq.html >wu-ftpd list archive: http://www.landfield.com/wu-ftpd/mail-archive/ > >-- > >Gregory A Lundberg Senior Partner, VRnet Company >1441 Elmdale Drive lundberg+wuftpd@vr.net >Kettering, OH 45409-1615 USA 1-800-809-2195 ------------------------------------------------------------------------------ Date: Thu, 25 Mar 1999 22:17:33 -0500 From: Gregory A Lundberg To: BUGTRAQ@netspace.org Subject: Re: wu-ftpd overflow. On Sun, 21 Mar 1999, CyberPsychotic wrote: > (cc'ed to bugtraq since I haven't seen yet any patches fixing this > problem were posted there) Yes, the exploit recently posted to Bugtraq takes advantage of the realpath() buffer overflows .. as they exist in the Redhat RPM version shipped on their 5. CD. The exploit may require some modification to be successfully used against other Linux/Intel systems and, of course, will need major changes to be used against other hardware or software platforms. About the exploit posted on Bugtraq: my read-through of the shows it does use the vulnerability through the MKD command. You are correct that some Academ beta versions do not use the source-provided vulnerable realpath() function for MKD. ISTM it should be fairly easy to modify the exploit to make use of other commands where a given Academ beta version _does_ use realpath(). Remember, the exploit is an _example_ of the problem, it does not reveal the true magnetude of the vulnerability. A positive test proves vulnerability while a negative test proves nothing. The vulnerable and non-vulnerable versions were outlined in the advisories which _were_ posted on Bugtraq. The realpath() problem was openly discussed on Bugtraq weeks (months? .. I'd have to look through the Bugtraq archives again) before the release of the advisories. The actively maintained versions of the wu-ftpd daemon were immedeately corrected as a result of the realpath() vulnerability discussions on Bugtraq, so they had been corrected for quite some time prior to Netect's research indicating there may be a problem. At the time of publication of the Netect/CERT Advisories, patches for wu-ftpd were unnecessary since the current, maintained, versions were not vulnerable. My patch file for wu-ftpd, which corrects the problem, is presently 644162 bytes in length, fixes several hundred other problems with the daemon, and is available via FTP from ftp://ftp.vr.net/pub/wu-ftpd/ for those silly enough to want it (I rather doubt it Aleph would allow it through to the Bugtraq the mailing list). I am not inclined to pull out the patches for realpath() because the entire pile of male bovine by-product was replaced. A patch file for the other major, maintained, version of wu-ftpd (BeroFTPD) is not available at all. Since today it would probably run well over 1 Meg, the maintainer sees no point in the fiction of 'patching'. He is also dis-inclined to pull out the realpath() changes since he and I co-operated on the complete replacement of the function (actually he did most of the initial work; I just debugged it). At about the time of the Netect/CERT Advisorie Redhat released updated RPMs for the vulnerable Academ 2.4.2-betas they distribute. I don't know whether they released before or after, but I do recall it was just a few hours before their availability was discussed on Bugtraq. Other versions (from wu-stl and academ) are not actively maintained and should not be used in production environments. Anyone running versions of wu-archive / the wu-ftpd daemon older than Academ's 2.4.2-beta-18 has more severe problems than this buffer overrun, so I see no point posting the patch. For them the correct solution is either updating to a more current version or manual operation of the power switch. The only current version still vulnerable when the CERT advisory was issued the Academ version 2.4.2-beta-18, which is (almost) not actively maintained. A week or two following the CERT advisory Academ silently released 2.4.2 (final). My knowledge of the code, and my direct research indicates: The 2.4.2 (final) version does not completely solve the problem. Nor does your patch. (Nor, for that matter, does the Redhat patch but that's a moot point since their patch does fix the problem for their Linux systems.) For systems using the realpath() function supplied with the source kit, a patch will work to correct, or at least hide, most, if not all, of the vulnerability. For other systems, whether or not the daemon is vulernable depends upon whether or not your vendor-supplied realpath() function is vulnerable (back to the original discussion on Bugtraq). The only change here from my recommendations appearing in the Netect and CERT advisories is that the number of potentially vulnerable systems has been reduced by those using the daemon-supplied realpath() function to only those with vendor-supplied vulnerable realpath() functions. To determine if your daemon uses the supplied function, look in /src/config/config. for a line reading something like: #define realpath realpath_on_steroids If this #define does NOT appear, contact your vendor concerning the vulnerability of the realpath() function, or upgrade to a more-current version of the daemon (yes, there are versions much more current that Academ's 2.4.2/final). Those wishing further information may contact me via the wu-ftpd support mailing list at mailto:wu-ftpd@wugate.wustl.edu .. subscription and unsubscription information for that mailing list are in the FAQ. The location of the latest versions of wu-ftpd can be found in the directory ftp://ftp.vr.net/pub/wu-ftpd/ wu-ftpd Resource Center: http://www.landfield.com/wu-ftpd/ wu-ftpd FAQ: http://www.cetis.hvu.nl/~koos/wu-ftpd-faq.html wu-ftpd list archive: http://www.landfield.com/wu-ftpd/mail-archive/ (The html version of the wu-ftpd list archive is currently not working, use the Unix mailbox format instead.) -- Gregory A Lundberg Senior Partner, VRnet Company 1441 Elmdale Drive lundberg+wuftpd@vr.net Kettering, OH 45409-1615 USA 1-800-809-2195 ------------------------------------------------------------------------------ Date: Sun, 21 Mar 1999 18:21:22 +0500 From: CyberPsychotic To: BUGTRAQ@netspace.org Subject: wu-ftpd overflow. ~ Has some1 located the file/function where ~ the overflow takes place ? Yes. I think overflow takes place is function realpath.c: look at the end of the function realpath(), which first concatinates everything together and then just does strcpy into result variable, which is pointer to buffer sized of MAXPATHLEN. You could either owerflow workpath variable in realpath, or, if your buffer is not too fat, it will be overflowed later, when function makedir returns (called from ftpcmd). in either case return address gets overflowed and it returns nowhere (or to your exploit code if you put there such, no big deal). I've made a couple of fixes to ftpd daemon to generate debugging info via syslog, so here's what I have: Mar 21 12:21:46 gear ftpd[21737]: ftpcmd:1294 (ftpcmd called makedir) Mar 21 12:21:46 gear ftpd[21737]: before 3180 (calling realpath line 3128) Mar 21 12:21:46 gear ftpd[21737]: overflow:180 (here overflow takes place) Mar 21 12:21:46 gear ftpd[21737]: overflow:210 (again. It's being copied twice) Mar 21 17:21:47 gear syslogd: Cannot glue message parts together Mar 21 12:21:46 gear ftpd[21737]: after 3180 (realpath line 3128 returns) /foo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Mar 21 17:21:47 gear AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Mar 21 12:21:47 gear ftpd[21737]: exiting on signal 11 oops..... now it attempted to execute piece at 0x41414141 addy.. Some previous beta releases of wu-ftpd are NOT vulneriable to this thing because they just don't call realpath function (which does overflow) from makedir() function. Here's quick patch I've done to this piece (cc'ed to bugtraq since I haven't seen yet any patches fixing this problem were posted there): --/cut here/-- --- ftpd.c.orig Mon Jul 6 15:14:25 1998 +++ ftpd.c Sun Mar 21 18:17:52 1999 @@ -3146,19 +3146,24 @@ if (mkdir(name, 0777) < 0) { if (errno == EEXIST){ - realpath(name, path); - reply(521, "\"%s\" directory exists", path); + if(realpath(name, path)) + reply(521, "\"%s\" directory exists.", path); + else reply(521,"path too long."); }else perror_reply(550, name); return; } - realpath(name, path); /* According to RFC 959: * The 257 reply to the MKD command must always contain the * absolute pathname of the created directory. * This is implemented here using similar code to the PWD command. * XXX - still need to do `quote-doubling'. */ + if(!realpath(name, path)) + if (strlen(path)!=0) + reply(257,"\"%s\" directory created name truncated.",path); + else reply(500,"no directory created. Path too long."); + else reply(257, "\"%s\" new directory created.", path); } --- realpath.c.orig Sun Mar 21 17:29:42 1999 +++ realpath.c Sun Mar 21 18:08:28 1999 @@ -40,6 +40,7 @@ #include #include #include +#include #ifndef HAVE_SYMLINK #define lstat stat @@ -55,10 +56,10 @@ #endif { struct stat sbuf; - char curpath[MAXPATHLEN], - workpath[MAXPATHLEN], - linkpath[MAXPATHLEN], - namebuf[MAXPATHLEN], + char curpath[MAXPATHLEN+1], + workpath[MAXPATHLEN+1], + linkpath[MAXPATHLEN+1], + namebuf[MAXPATHLEN+1], *where, *ptr, *last; @@ -75,7 +76,7 @@ return(NULL); } - strcpy(curpath, pathname); + strncpy(curpath, pathname,MAXPATHLEN); if (*pathname != '/') { uid_t userid; @@ -93,7 +94,7 @@ #else if (!getwd(workpath)) { #endif - strcpy(result, "."); + strncpy(result, ".",MAXPATHLEN); seteuid(userid); enable_signaling(); /* we can allow signals once again: kinch */ return (NULL); @@ -142,9 +143,13 @@ for (last = namebuf; *last; last++) continue; if ((last == namebuf) || (*--last != '/')) - strcat(namebuf, "/"); - strcat(namebuf, where); - + strncat(namebuf, "/",MAXPATHLEN-strlen(namebuf)); + strncat(namebuf, where,MAXPATHLEN-strlen(namebuf)); + if (strlen(namebuf)+strlen(where)>=MAXPATHLEN) { + syslog(LOG_DAEMON|LOG_NOTICE,"possible buffer overflow attempt"); + return(NULL); + } + where = ++ptr; if (lstat(namebuf, &sbuf) == -1) { strcpy(result, namebuf); @@ -163,8 +168,13 @@ if (*linkpath == '/') *workpath = '\0'; if (*where) { - strcat(linkpath, "/"); - strcat(linkpath, where); + strncat(linkpath, "/",MAXPATHLEN-strlen(linkpath)); + strncat(linkpath, where,MAXPATHLEN-strlen(linkpath)); + if (strlen(namebuf)+strlen(where)>=MAXPATHLEN) { + syslog(LOG_DAEMON|LOG_NOTICE, + "possible buffer overflow attempt"); + return(NULL); + } } strcpy(curpath, linkpath); goto loop;