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