|
COMMAND Qpopper buffer overflow condition SYSTEMS AFFECTED Qpopper 4.0.3 and 4.0.4. default install. PROBLEM In Marcel Fodor [http://mantra.freeweb.hu] security bug report : In : pop_bull.c ----------- int CopyOneBull ( POP *p, long bnum, char *name ) { FILE *bull; char buffer [ MAXMSGLINELEN ]; BOOL in_header = TRUE; BOOL first_line = TRUE; int nchar; int msg_num; int msg_vis_num = 0; int msg_ends_in_nl = 0; char bullName [ 256 ]; MsgInfoList *mp; /* Pointer to message info list */ . . . sprintf ( bullName, \"%s/%s\", p->bulldir, name ); ------------ The bullNmae buffer is 256 bytes long, but in the user\'s configuration file you can define it up to MAXLINELEN-1-sizeof(\"set bulldir=\") ~1010 bytes. ~/.qpopper-options -------------- set bulldir=AAAAAAAAAAA.....AAAAAAAAAAAAAAA // ( bulldir must exist) -------------- Since we have only 1010+256 bytes(p->bulldir+name) it is NOT enough to overflow the funcion`s stack and overwrite EIP. As you see the following registers can be overwritten: BOOL in_header = TRUE; BOOL first_line = TRUE; int nchar; int msg_num; int msg_vis_num = 0; int msg_ends_in_nl = 0; char bullName [ 256 ]; --------------------- MsgInfoList *mp; /* Pointer to message info list */ There are two valuable registers: 1. msg_num 2. msg_vis_num As the code runs on, server wants to find memory location for the actual message. Here it is: mp = p->mlp + msg_num - 1; As we have control over msg_num, we can walk forward in memory, by steps of 0x40 bytes (sizeof(*mp)). On my system giving the value of 0x2dfe423 to msg_num, mp will point to 0xbfffbe6c Now code runs on, and fill up properties. ++mp; mp->number = msg_num; mp->visible_num = ++msg_vis_num; <---- we have this mp->lines = 0; mp->body_lines = 0; mp->offset = ftell(p->drop); mp->del_flag = FALSE; mp->hide_flag = FALSE; mp->retr_flag = FALSE; So, the main thing is the 0x40 bytes steps. For this, the risk of the bug is low. SOLUTION Workaround : ========== Servers, not processing user\'s configuration file (~/.qpopper-options) are insensible to this bug. ( qpopper -u) Patch : ===== None yet ?