5564326 2000-10-08 22:03 /66 rader/ Brevbäraren (som är implementerad i) Python Mottagare: Bugtraq (import) <13153> Ärende: sendmail -bt negative index bug... ------------------------------------------------------------ From: Michal Zalewski <lcamtuf@DIONE.IDS.PL> To: BUGTRAQ@SECURITYFOCUS.COM Message-ID: <Pine.LNX.4.10.10010081417330.1498-100000@localhost> 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. <=-----= (5564326) ------------------------------------------(Ombruten)