26th Sep 2002 [SBWID-5316]
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 ?