wu-ftpd overflow.

From: CyberPsychotic (fygraveat_private)
Date: Sun Mar 21 1999 - 05:21:22 PST

  • Next message: Mnemonix: "Index Server 2.0 and the Registry"

    ~ 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