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:


int
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 };
167:
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;
179:

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;
743:
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.

Create a free website or blog at WordPress.com.