OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
 
From: Paul Starzetz (paulSTARZETZ.DE)
Date: Mon Mar 05 2001 - 11:15:01 CST

  • Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

    1. Abstract
    -----------

    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

    2. Details
    ----------

    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, I 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 userhost pair do _not_
    need to have OPER priviledges prior to use tkserv. Or in other words, requesting at least one
    userhost pair in tkserv.access to have OPER priviledges prior to using tkserv results in remote
    buffer overflow vulnerability.

    Of course, having a matching userhost pair, but no tkserv access (which is not so uncommon, believe
    me.. there are some configuration pitfalls concerning the userhost lines, which I don't want to
    reveal ;-) the vulnerability can be exploited too.

    So overflowing 'reason' results in overwriting saved EIP with well known consequences.

    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, I know, with current BIND it wouldn't work...). I think, this is not
    exploitable in the wild.

    3. Solution
    -----------

    See discussion. Do not request opered access to your tkserv. Update as soon as possible.

    IhaQueR Security Research.