Bugtraq mailing list archives

sendmail -bt negative index bug...


From: Michal Zalewski <lcamtuf () DIONE IDS PL>
Date: Sun, 8 Oct 2000 15:12:46 +0200

This problem, AFAIK, affects all known Sendmail releases. Exploitability
has been not proven, so no need to be afraid (for now ;).

[ Btw: I'm looking for a good job - http://lcamtuf.hack.pl/job.html ]

Sendmail, launched with -bt command-line switch, enters it's special
"address test" mode. It is not dropping root privledges (why?), and
accepting user-supplied input. Several commands provided in this mode had
broken implementation. One of the most serious bugs is missing check
before calling setclass() functions. I discovered it while playing with
sendmail binary (well, .C{a_lot_of_As}something exited with SEGV, and I
thought it's an overflow ;). Unfortunately, it appeared to be missing
return condition before calling setclass(), which caused this macro to be
called with negative index value (-1). But hey... Well, I played a little
bit more, and found simple .Cxval commands (x == one-character class name)
are handled differently from .C{name}val commands. In first case, class
number passed to setclass() is equal to numerical value of character
representing macro name. Why - well, see the implementation, idea wasn't
bad - but using signed char value to index positive-indexed table (0..255)
wasn't really good idea. I tried another trick - .Cósomething (where 'ó'
was the class name). And yes - success! This time, as 'ó' character,
stored as signed (default on eg. Linux boxes) character, was equal to -13:

Program received signal SIGSEGV, Segmentation fault.
0x80828ea in setclass (class=-13, str=0xbfffdf7c "s") at readcf.c:2803
2803                    setbitn(class, s->s_class);

See...

#define _BITWORD(bit)   ((bit) / (BYTEBITS * sizeof (int)))
#define _BITBIT(bit)    ((unsigned int)1 << ((bit) % (BYTEBITS * sizeof (int))))

/* set bit number N */
#define setbitn(bit, map)       (map)[_BITWORD(bit)] |= _BITBIT(bit)

So, after parsing, we have:

  s->s_class[-4] |= 524288;

What can I say? As there's no range checking in C, negative indexes just
so dangerous as excessive indexes (aka buffer overflows ;)! I don't want
to speculate on exploitability of this code (you have to examine if
there's something interesting in memory after specific array, and,
eventually, look for other bugs of this type, eg. in .D commands), but I'm
affraid negative index bugs are too often overlooked or ignored:

-- demo.c --
main() {
  int test[10];
  char text[5]="test";
  test[-2]=0x6b636168;
  puts(text);
}
-- EOF --

Regards,
_______________________________________________________
Michal Zalewski [lcamtuf () tpi pl] [tp.internet/security]
[http://lcamtuf.na.export.pl] <=--=> bash$ :(){ :|:&};:
=-----=> God is real, unless declared integer. <=-----=


Current thread: