~ 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/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Mar 21 17:21:47 gear AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 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 <sys/stat.h> #include <sys/param.h> #include <string.h> +#include <syslog.h> #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;
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:39:37 PDT