fts, du, find

From: Stas Kisel (stasat_private)
Date: Wed May 12 1999 - 03:32:42 PDT

  • Next message: Alan Coopersmith: "Re: Sun Microsystems Leaks extensive Amounts of Information About"

    Hi.
    
    I use FreeBSD-2.2.8 and FreeBSD-2.2.7 and I know that these versions are
    no longer supported, but:
    1. There are many people still using 2.2
    2. This bug probably applies to FreeBSD-3.1 and ever to OpenBSD and other.
    
    Approximately a month ago I've found a very strange behaviour of 'du'
    with long direstory structures. I left this alone due to lack of time,
    but some days ago I saw an article on bugtraq concerning similar
    behaviour of 'find'.
    
    There is a one bug in libc causing this behaviour. I have a patch, but
    I did not tested it much ;)
    
    Both 'find' and 'du' use 'fts' (fts_read,...) functions to traverse
    directory structure.
    fts uses realloc() to reallocate memory in quite complex lists.
    There is a bug in adjusting pointers after realloc().
    So when dealing with large directory structures (when realloc() needed),
    some pointers can point to free()-ed memory.
    
    I have no exploit and probably will no have a free time (I think
    3 days is more than enough) for doing it, but I beleive it is
    possible to exploit this bug using carefully designed directory
    tree to execute arbitrary commands as root during
    /etc/daily->/etc/security->find.
    REMOTE ROOT EXPLOIT (POSSIBLE).
    At least it is possible to hide setuid binary this way in home dir or in /tmp.
    
    The following patch is designed for FreeBSD-2.2.8-RELEASE libc.
    There was the following ID in the beginning of the source file.
    /*      $OpenBSD: fts.c,v 1.9 1997/08/02 00:13:49 millert Exp $ */
    I've only tested this patch on one machine during one day, so
    it is probably buggy.
    If you'll apply this patch, please drop me a line if there was any side effect
    and I'll do a followup in the bugtraq, say, on the Friday.
    
    ------------------ patch ----------------------------------------
    --- /usr/src/lib/libc/gen/fts.c.orig	Tue May 11 13:37:49 1999
    +++ /usr/src/lib/libc/gen/fts.c	Wed May 12 13:16:08 1999
    @@ -740,8 +740,26 @@
     	 * If had to realloc the path, adjust the addresses for the rest
     	 * of the tree.
     	 */
    -	if (adjaddr)
    +	if (adjaddr){
     		fts_padjust(sp, adjaddr);
    +		/* Adjust the list, because we want to return it robust. */
    +/* fix p->fts_path and p->fts_accpath
    +   p->fts_accpath can be:
    +	either cur->fts_path	(adjust, because cur is already adjusted)
    +	either p->fts_path	(adjust)
    +	either p->fts_name	(do not adjust)
    +   I'm also almost sure that in first case cur->fts_path=p->fts_path...
    +*/
    +#define	ADJUST1(p) if((p)->fts_path != adjaddr){	\
    +	if((p)->fts_accpath != (p)->fts_name){		\
    +		(p)->fts_accpath =			\
    +			(char *)adjaddr + ((p)->fts_accpath - (p)->fts_path);\
    +	}						\
    +	(p)->fts_path = adjaddr;			\
    +}
    +		for (p = head; p; p = p->fts_link)
    +			ADJUST1(p);
    +	}
    
     	/*
     	 * If not changing directories, reset the path back to original
    @@ -974,18 +992,18 @@
     {
     	FTSENT *p;
    
    -#define	ADJUST(p) {							\
    +#define	ADJUST2(p) {							\
     	(p)->fts_accpath =						\
     	    (char *)addr + ((p)->fts_accpath - (p)->fts_path);		\
     	(p)->fts_path = addr;						\
     }
     	/* Adjust the current set of children. */
     	for (p = sp->fts_child; p; p = p->fts_link)
    -		ADJUST(p);
    +		ADJUST2(p);
    
     	/* Adjust the rest of the tree. */
     	for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
    -		ADJUST(p);
    +		ADJUST2(p);
     		p = p->fts_link ? p->fts_link : p->fts_parent;
     	}
     }
    ------------------ endpatch ----------------------------------------
    
    --
    Stas Kisel
    Open Tavrical College		Sysadmin	stasat_private
    Simferopol State University	Web-designer	stasat_private
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:45:49 PDT