COMMAND
tkserv
SYSTEMS AFFECTED
IRCd's tkserv
PROBLEM
Paul Starzetz found following. There are 3 major bugs in the
current IRCd distribution (as used on the IRCnet for example).
The included service daemon 'tkserv' (tkserv.c v1.3.0 and all
previous versions) suffers from:
a) remote exploitable buffer overflow while querying tklines
b) memory leck due to strdup'ing a string and not freeing the
mem
c) format string bug while reading the ircd's config file
a) There is an buffer overflow in the 'void squery_tkline(char
**args)' from tkserv.c. The bad part is (*):
/* User wants to add tkline(s). */
if (lifetime > 0)
{
passwd = args[4];
pattern = args[6];
(*) strcpy(reason, args[7]);
i = 8;
/* I know... */
while(args[i] && *args[i])
{
strncat(reason, " ", TKS_MAXKILLREASON - strlen(reason) - 1);
strncat(reason, args[i], TKS_MAXKILLREASON - strlen(reason) - 1);
i++;
}
where reason is defined to be a static char buffer 'char
reason[TKS_MAXKILLREASON]' and TKS_MAXKILLREASON is defined to
be only 128 characters. Sending an carefully crafted tkline
squery to vulnerable tkserv may result in remote code execution
and further compromise. Indeed after looking at a running
tkserv in gdb, Paul found that exploitation of this flaw should
be very easy. There are only few conditions to meet, e.g. the
*args[i] part...
We also need to meet the condition 'must_be_opered()' which is
checked before the vulnerable code is entered by tkserv. This
occurs, if in the tkserv.access file there is at least one
access line _not_ containing "!" as the first character, which
means that the corresponding user@host pair do _not_ need to
have OPER priviledges prior to use tkserv. Or in other words,
requesting at least one user@host pair in tkserv.access to have
OPER priviledges prior to using tkserv results in remote
buffer overflow vulnerability.
Of course, having a matching user@host pair, but no tkserv
access (which is not so uncommon, believe me.. there are some
configuration pitfalls concerning the user@host lines, which
Paul don't want to reveal, the vulnerability can be exploited
too.
So overflowing 'reason' results in overwriting saved EIP with
well known consequences.
One needs at least one _non_ OPERED line in tkserv.access in
order to be vulnerable to the mentioned buffer overflow attack.
b) The bad part is (**):
int must_be_opered()
{
FILE *fp;
/* if the access file exists, check for auth */
if ((fp = fopen(TKSERV_ACCESSFILE, "r")) != NULL)
{
char buffer[TKS_MAXBUFFER];
char *access_uh, *token, *uh;
while (fgets(buffer, TKS_MAXBUFFER, fp))
{
uh = (char *) (strchr(nuh, '!') + 1);
token = (char *) strtok(buffer, " ");
if (token)
{
(**) access_uh = (char *) strdup(token);
}
the pointer returned by strdup is never a subject a free()
call. So stressing the tkserv with many unauthorized (!)
squery's results in excessive memory usage in effectively in
denying the service and maybe other services running on the
vulnerable box.
c) While the tkserv parses the ircd.conf file, e.g. after
requesting a new k-line (the original ircd.conf is read
line-by-line and the modified copy written to ircd.conf.tmp,
which is copied to ircd.conf after tkserv has finished reading
the original config file) there is a vulnerable call to fprintf
(***):
int check_tklines(char *host, char *user, int lifetime)
{
FILE *iconf, *iconf_tmp;
if ((iconf = fopen(CPATH, "r")) && (iconf_tmp = fopen(TKSERV_IRCD_CONFIG_TMP, "w")))
{
int count = 0, found = 0;
time_t now;
char buffer[TKS_MAXBUFFER];
char buf_tmp[TKS_MAXBUFFER];
/* just in case... */
chmod(TKSERV_IRCD_CONFIG_TMP, S_IRUSR | S_IWRITE);
now = time(NULL);
while (fgets(buffer, TKS_MAXBUFFER, iconf))
{
if ((*buffer != 'K') || (!strstr(buffer, "tkserv")))
{
(***) fprintf(iconf_tmp, buffer);
}
the original ircd.conf is fprint'ed line by line to a temporary
copy, so if one can include some format conversion operators
there, the code will fail (hm, what about /timer1234 99999 5
/msg someoper hey moron... ok, we know, with current BIND it
wouldn't work...). This should not be exploitable in the wild.
SOLUTION
See discussion. Do not request opered access to your tkserv.
Update as soon as possible. This is NOT current IRCnet IRCD, that
is vulnerable. All files in contrib/ directory are not part of
IRCD daemon, they are related to it.